Import Cobalt 21.master.0.267507

Includes the following patches:
  https://cobalt-review.googlesource.com/c/cobalt/+/5630
    by devin.cai@mediatek.com
  https://cobalt-review.googlesource.com/c/cobalt/+/5710
    by p.mirgos@samsung.com
  https://cobalt-review.googlesource.com/c/cobalt/+/5730
    by lizhi.fan@samsung.com
diff --git a/src/starboard/CHANGELOG.md b/src/starboard/CHANGELOG.md
index 7217425..c535b8b 100644
--- a/src/starboard/CHANGELOG.md
+++ b/src/starboard/CHANGELOG.md
@@ -14,6 +14,234 @@
 can be found in the comments of the "Experimental Feature Defines" section of
 [configuration.h](configuration.h).
 
+## Version 12
+###  Add support for platform-based UI navigation.
+
+The system can be disabled by implementing the function
+`SbUiNavGetInterface()` to return `false`.  Platform-based UI navigation
+allows the platform to receive feedback on where UI elements are located and
+also lets the platform control what is selected and what the scroll
+parameters are.
+
+NOTE: This API is not used in the production web app yet, so please use the
+stub implementation for `SbUiNavGetInterface()` for now.
+
+### Require the OpenGL and Skia renderers on all platforms.
+
+The system must implement `SbGetGlesInterface()` in `starboard/gles.h`
+or use the provided stub implementation.
+
+This change also effectively deprecates the gyp variable
+"enable_map_to_mesh" in favor of CobaltGraphicsExtensionApi function
+`IsMapToMeshEnabled()` and the command line switch --disable_map_to_mesh.
+Now, Cobalt will assume the platform supports map_to_mesh, so platforms that
+do not will have to have return |false| from `IsMapToMeshEnabled()` or use
+the provided command line switch.
+
+### Require the captions API.
+
+The system must implement the captions functions in
+`starboard/accessibility.h` or use the provided stub implementations.
+System caption can be disabled by implementing the function
+`SbAccessibilityGetCaptionSettings(SbAccessibilityCaptionSettings*
+caption_settings)` to return false as the stub implementation does.
+This change also deprecates the SB_HAS_CAPTIONS flag.
+
+### Require compilation with IPv6.
+
+Cobalt must be able to determine at runtime if the system supports IPv6.
+IPv6 can be disabled by defining SB_HAS_IPV6 to 0.
+
+### Require the microphone API.
+
+The system must implement the microphone functions in
+`starboard/microphone.h` or use the provided stub functions.
+The microphone can be disabled by having `SbMicrophoneCreate()` return
+|kSbMicrophoneInvalid|.
+This change also deprecates the SB_HAS_MICROPHONE flag.
+
+###  Require the memory mapping API.
+
+The system must implement the memory mapping functions in
+`starboard/memory.h` and `starboard/shared/dlmalloc.h` or use the provided
+stub implementations.
+This change also deprecates the SB_HAS_MMAP flag.
+
+### Require the on screen keyboard API.
+
+The system must implement the on screen keyboard functions in
+`starboard/window.h` or use the provided stub implementations.
+The on screen keyboard can be disabled by implementing the function
+`SbWindowOnScreenKeyboardIsSupported()` to return false
+as the stub implementation does.
+
+### Require speech recognizer API.
+
+The system must implement the functions in `starboard/speech_recognizer.h`
+or use the provided stub implementations.
+The speech recognizer can be disabled by implementing the function
+`SbSpeechRecognizerIsSupported()` to return `false` as the stub
+implementation does.
+
+### Require the speech synthesis API.
+
+The system must implement the speech synthesis function in
+`starboard/speech_synthesis.h` or use the provided stub implementations.
+Speech synthesis can be disabled by implementing the function
+`SbSpeechSynthesisIsSupported()` to return false as the stub
+implementation does.
+
+### Require the time thread now API.
+
+The system must implement the time thread now functions in
+`starboard/time.h` or use the provided stub implementations.
+Time thread now can be disabled by implementing the function
+`SbTimeIsTimeThreadNowSupported()` to return false as the stub
+implementation does.
+
+### Add SbFileAtomicReplace API.
+
+Introduce the Starboard function SbFileAtomicReplace() to provide the ability
+to atomically replace the content of a file.
+
+### Introduces new system property kSbSystemPathStorageDirectory.
+
+Path to directory for permanent storage. Both read and write
+access are required.
+
+### Introduce Starboard Application Binary Interface (SABI) files.
+
+SABI files are used to describe the configuration for targets such that two
+targets, built with the same SABI file and varying toolchains, have
+compatible Starboard APIs and ABIs.
+
+With this define, we have:
+1) Moved architecture specific defines and configurations from
+  configuration_public.h and *.gyp[i] files into SABI files.
+2) Included the appropriate SABI file in each platform configuration.
+3) Included the //starboard/sabi/sabi.gypi file in each platform
+  configuration which consumes SABI file fields and defines a set of
+  constants that are accessible when building.
+4) Provided a set of tests that ensure the toolchain being used produces
+  an executable or shared library that conforms to the included SABI file.
+
+For further information on what is provided by SABI files, or how these
+values are consumed, take a look at //starboard/sabi.
+
+### Updates the API guarantees of SbMutexAcquireTry.
+
+SbMutexAcquireTry now has undefined behavior when it is invoked on a mutex
+that has already been locked by the calling thread. In addition, since
+SbMutexAcquireTry was used in SbMutexDestroy, SbMutexDestroy now has
+undefined behavior when invoked on a locked mutex.
+
+### Migrate the Starboard configuration variables from macros to extern consts.
+
+The migration allows Cobalt to make platform level decisions at runtime
+instead of compile time which lets us create a more comprehensive Cobalt
+binary.
+
+This means Cobalt must remove all references to these macros that would not
+translate well to constants, i.e. in compile time references or initializing
+arrays. Therefore, we needed to change the functionality of the function
+`SbDirectoryGetNext` in "starboard/directory.h". Because we do not want to
+use variable length arrays, we pass in a c-string and length to the function
+to achieve the same result as before when passing in a `SbDirectoryEntry`.
+
+A platform will define the extern constants declared in
+"starboard/configuration_constants.h". The definitions are done in
+"starboard/<PLATFORM_PATH>/configuration_constants.cc".
+
+The exact mapping between macros and extern variables can be found in
+"starboard/shared/starboard/configuration_constants_compatibility_defines.h"
+though the naming scheme is very nearly the same: the old SB_FOO macro will
+always become the constant kSbFoo.
+
+### Improve player creation and output mode query.
+
+1. Introduce the new type SbPlayerCreationParam that holds the common
+parameters used to create an SbPlayer() and to query for the output mode
+support.
+
+2. Replace SbPlayerOutputModeSupported() by SbPlayerGetPreferredOutputMode()
+so the SbPlayer implementation can explicitly indicate its preference on
+output mode, when all output modes are supported.
+For example, Cobalt used to always query for |kSbPlayerOutputModePunchOut|
+first, without providing details about the video going to be played, and
+not query for output modes if punch out is supported.  The new interface
+allows the implementation to fine tune its output mode.  For example, it
+may decide to use |kSbPlayerOutputModeDecodeToTexture| for low resolution
+videos.
+
+### Introduce error handling into reference SbAudioSinkPrivate.
+
+The implementation is in:
+"starboard/shared/starboard/audio_sink/audio_sink_internal.*".
+
+### Change the thread types to be portable with stable ABI.
+
+The following types were updated:
+SbThread, SbMutex, SbOnce and SbConditionVariable.
+
+### Introduce support of cbcs encryption scheme into SbDrmSystem.
+
+The definition follows ISO/IEC 23001 part 7.
+
+### Add link register to SbThreadContext.
+
+### Make GYP configuration variables cobalt extensions instead.
+
+This change moves all of the GYP configuration variables to be members of
+the struct declared in "cobalt/extension/configuration.h". All members are
+function pointers that can be set for each platform, otherwise defaults
+will be used. These can be referenced through functions declared in
+"cobalt/configuration/configuration.h", which will use the extension API if
+available, but will otherwise fall back onto default values.
+
+### Add the PCLMULQDQ instruction feature.
+
+The PCLMULQDQ was added to the Starboard CPU features interface
+for x86 architectures.
+
+###  |content_type| is added to SbMediaIsVideoSupported() and
+SbMediaIsAudioSupported().
+
+### Enables a test that checks that Opus is supported.
+
+### Deprecated the Blitter API.
+
+Blitter API is no longer supported on any platform. Use the OpenGL ES
+interface instead.
+
+### Deprecated the Crypto API.
+
+Crypto API is no longer supported on any platform. BoringSSL CPU
+optimizations are used instead.
+
+### Deprecate the SB_HAS_VIRTUAL_REGIONS flag as all platforms define it to 0.
+
+### Deprecate the usage of SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER.
+
+### Deprecated unused enums |kSbPlayerDecoderStateBufferFull| and
+|kSbPlayerDecoderStateDestroyed|.
+
+### Deprecate the |SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING| macro.
+
+### Deprecated 'cobalt_minimum_frame_time_in_milliseconds'.
+
+The variable 'cobalt_minimum_frame_time_in_milliseconds' is deprecated
+in favor of the usage of
+'CobaltExtensionGraphicsApi::GetMinimumFrameIntervalInMilliseconds' API.
+The declaration of 'GetMinimumFrameIntervalInMilliseconds' can be found
+in cobalt/renderer/backend/graphics_context.h
+
+### Deprecate support for GLES3 features.
+
+### Deprecate Web Extension support.
+
+The Platform Services API should be used
+instead. See cobalt/doc/platform_services.md.
+
 ## Version 11
 
 ### Add arguments to `SbMediaIsVideoSupported`.
diff --git a/src/starboard/accessibility.h b/src/starboard/accessibility.h
index f270a6c..05883ae 100644
--- a/src/starboard/accessibility.h
+++ b/src/starboard/accessibility.h
@@ -63,7 +63,7 @@
 SB_EXPORT bool SbAccessibilityGetDisplaySettings(
     SbAccessibilityDisplaySettings* out_settings);
 
-#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+#if SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
 // Enum for possible closed captioning character edge styles.
 typedef enum SbAccessibilityCaptionCharacterEdgeStyle {
   kSbAccessibilityCaptionCharacterEdgeStyleNone,
@@ -224,7 +224,7 @@
 //    or off (false).
 SB_EXPORT bool SbAccessibilitySetCaptionsEnabled(bool enabled);
 
-#endif  // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/src/starboard/android/apk/app/build.gradle b/src/starboard/android/apk/app/build.gradle
index 07ab31a..d166cce 100644
--- a/src/starboard/android/apk/app/build.gradle
+++ b/src/starboard/android/apk/app/build.gradle
@@ -40,10 +40,20 @@
 println "TARGET: ${cobaltTarget}"
 
 android {
-    compileSdkVersion 29
-    buildToolsVersion "29.0.2"
+    compileSdkVersion 'android-R'
+    buildToolsVersion '30.0.0-rc4'  // TODO: Update with release version.
     ndkVersion NDK_VERSION
 
+    aaptOptions {
+        // The following pattern matches the default aapt pattern with the
+        // exception that it is missing the blanket ignore wildcard (!.*) that
+        // matches any "hidden" file, i.e. files with names beginning with |.|.
+        //
+        // For more information check out |gDefaultIgnoreAssets| in AOSP
+        // frameworks/base/tools/aapt/AaptAssets.cpp.
+        ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~'
+    }
+
     signingConfigs {
         // A signing config that matches what is implicitly used for the "debug" build type.
         debugConfig {
@@ -56,7 +66,7 @@
     defaultConfig {
         applicationId "dev.cobalt.coat"
         minSdkVersion 21
-        targetSdkVersion 29
+        targetSdkVersion 30
         versionCode 1
         versionName "${buildId}"
         manifestPlaceholders = [applicationName: "CoAT: ${cobaltTarget}"]
@@ -167,6 +177,6 @@
     implementation 'androidx.annotation:annotation:1.1.0'
     implementation 'androidx.leanback:leanback:1.0.0'
     implementation 'androidx.legacy:legacy-support-v4:1.0.0'
-    implementation 'com.google.android.gms:play-services-auth:17.0.0'
+    implementation 'com.google.android.gms:play-services-auth:18.0.0'
     implementation 'com.google.protobuf:protobuf-lite:3.0.1'
 }
diff --git a/src/starboard/android/apk/app/src/app/java/dev/cobalt/app/MainActivity.java b/src/starboard/android/apk/app/src/app/java/dev/cobalt/app/MainActivity.java
index 04e70a8..3b37bf1 100644
--- a/src/starboard/android/apk/app/src/app/java/dev/cobalt/app/MainActivity.java
+++ b/src/starboard/android/apk/app/src/app/java/dev/cobalt/app/MainActivity.java
@@ -18,7 +18,6 @@
 import dev.cobalt.account.UserAuthorizerImpl;
 import dev.cobalt.coat.CobaltActivity;
 import dev.cobalt.coat.StarboardBridge;
-import dev.cobalt.feedback.NoopFeedbackService;
 import dev.cobalt.util.Holder;
 
 /**
@@ -41,12 +40,10 @@
         };
     UserAuthorizerImpl userAuthorizer =
         new UserAuthorizerImpl(getApplicationContext(), activityHolder, stopRequester);
-    NoopFeedbackService feedbackService = new NoopFeedbackService();
     return new StarboardBridge(
         getApplicationContext(),
         activityHolder,
         userAuthorizer,
-        feedbackService,
         args,
         startDeepLink);
   }
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/account/UserAuthorizerImpl.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/account/UserAuthorizerImpl.java
index 1902635..1d96237 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/account/UserAuthorizerImpl.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/account/UserAuthorizerImpl.java
@@ -35,11 +35,13 @@
 import com.google.android.gms.auth.GoogleAuthUtil;
 import com.google.android.gms.auth.UserRecoverableAuthException;
 import com.google.android.gms.common.AccountPicker;
+import com.google.android.gms.common.AccountPicker.AccountChooserOptions;
 import dev.cobalt.coat.R;
 import dev.cobalt.util.Holder;
 import dev.cobalt.util.Log;
 import dev.cobalt.util.UsedByNative;
 import java.io.IOException;
+import java.util.Arrays;
 
 /**
  * Java side implementation for starboard::android::shared::cobalt::AndroidUserAuthorizer.
@@ -408,9 +410,12 @@
    * one account on the device. If there are no accounts on the device it shows the UI to add one.
    */
   private Intent newChooseAccountIntent(Account defaultAccount) {
-    String[] allowableAccountTypes = {GOOGLE_ACCOUNT_TYPE};
-    return AccountPicker.newChooseAccountIntent(
-        defaultAccount, null, allowableAccountTypes, true, null, null, null, null);
+    AccountChooserOptions chooserOptions = new AccountChooserOptions.Builder()
+        .setSelectedAccount(defaultAccount)
+        .setAllowableAccountsTypes(Arrays.asList(GOOGLE_ACCOUNT_TYPE))
+        .setAlwaysShowAccountPicker(true)
+        .build();
+    return AccountPicker.newChooseAccountIntent(chooserOptions);
   }
 
   /**
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltA11yHelper.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltA11yHelper.java
index b0fcb50..4c8180f 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltA11yHelper.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltA11yHelper.java
@@ -14,17 +14,15 @@
 
 package dev.cobalt.coat;
 
-import static dev.cobalt.util.Log.TAG;
-
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import androidx.core.view.ViewCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 import androidx.customview.widget.ExploreByTouchHelper;
-import dev.cobalt.util.Log;
 import java.util.BitSet;
 import java.util.List;
 
@@ -56,7 +54,7 @@
   // This set tracks whether onPopulateNodeForVirtualView has been
   // called for each virtual view id.
   private final BitSet nodePopulatedSet = new BitSet(9);
-  private final Handler handler = new Handler();
+  private final Handler handler = new Handler(Looper.getMainLooper());
   private boolean unhandledInput;
   private boolean hasInitialFocusBeenSet;
 
@@ -98,7 +96,7 @@
           }
         });
 
-    // There is a knwon Android bug about setting focus too early
+    // There is a known Android bug about setting focus too early
     // taking no effect. The impact for Cobalt is that sometimes after
     // we click on a video, TalkBack sees nothing in focus in the watch
     // page if no user input happens. To avoid this bug we have to
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java
index 8b89697..754f495 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java
@@ -22,8 +22,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.media.AudioDeviceInfo;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
@@ -31,12 +29,11 @@
 import android.net.NetworkCapabilities;
 import android.os.Build;
 import android.util.Size;
-import android.view.WindowManager;
+import android.view.Display;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.CaptioningManager;
 import androidx.annotation.RequiresApi;
 import dev.cobalt.account.UserAuthorizer;
-import dev.cobalt.feedback.FeedbackService;
 import dev.cobalt.media.AudioOutputManager;
 import dev.cobalt.media.CaptionSettings;
 import dev.cobalt.media.CobaltMediaSession;
@@ -62,7 +59,6 @@
   private CobaltSystemConfigChangeReceiver sysConfigChangeReceiver;
   private CobaltTextToSpeechHelper ttsHelper;
   private UserAuthorizer userAuthorizer;
-  private FeedbackService feedbackService;
   private AudioOutputManager audioOutputManager;
   private CobaltMediaSession cobaltMediaSession;
   private VoiceRecognizer voiceRecognizer;
@@ -96,7 +92,6 @@
       Context appContext,
       Holder<Activity> activityHolder,
       UserAuthorizer userAuthorizer,
-      FeedbackService feedbackService,
       String[] args,
       String startDeepLink) {
 
@@ -111,7 +106,6 @@
     this.sysConfigChangeReceiver = new CobaltSystemConfigChangeReceiver(appContext, stopRequester);
     this.ttsHelper = new CobaltTextToSpeechHelper(appContext, stopRequester);
     this.userAuthorizer = userAuthorizer;
-    this.feedbackService = feedbackService;
     this.audioOutputManager = new AudioOutputManager(appContext);
     this.cobaltMediaSession =
         new CobaltMediaSession(appContext, activityHolder, audioOutputManager);
@@ -152,7 +146,6 @@
     // Bring our platform services to life before resuming so that they're ready to deal with
     // whatever the web app wants to do with them as part of its start/resume logic.
     cobaltMediaSession.resume();
-    feedbackService.connect();
     for (CobaltService service : cobaltServices.values()) {
       service.beforeStartOrResume();
     }
@@ -166,7 +159,6 @@
     // the launcher is visible our "Now Playing" card is already gone. Then Cobalt and the web app
     // can take their time suspending after that.
     cobaltMediaSession.suspend();
-    feedbackService.disconnect();
     for (CobaltService service : cobaltServices.values()) {
       service.beforeSuspend();
     }
@@ -421,21 +413,6 @@
 
   @SuppressWarnings("unused")
   @UsedByNative
-  void sendFeedback(
-      HashMap<String, String> productSpecificData, String categoryTag, byte[] screenshotData) {
-    // Convert the screenshot byte array into a Bitmap.
-    Bitmap screenshotBitmap = null;
-    if ((screenshotData != null) && (screenshotData.length > 0)) {
-      screenshotBitmap = BitmapFactory.decodeByteArray(screenshotData, 0, screenshotData.length);
-      if (screenshotBitmap == null) {
-        Log.e(TAG, "Unable to decode a screenshot from the data.");
-      }
-    }
-    feedbackService.sendFeedback(productSpecificData, categoryTag, screenshotBitmap);
-  }
-
-  @SuppressWarnings("unused")
-  @UsedByNative
   void updateMediaSession(
       int playbackState,
       long actions,
@@ -528,18 +505,13 @@
       return false;
     }
 
-    Activity activity = activityHolder.get();
-    if (activity == null) {
-      return false;
-    }
-
-    WindowManager windowManager = activity.getWindowManager();
-    if (windowManager == null) {
+    Display defaultDisplay = DisplayUtil.getDefaultDisplay(activityHolder.get());
+    if (defaultDisplay == null) {
       return false;
     }
 
     int[] supportedHdrTypes =
-        windowManager.getDefaultDisplay().getHdrCapabilities().getSupportedHdrTypes();
+        defaultDisplay.getHdrCapabilities().getSupportedHdrTypes();
     for (int supportedType : supportedHdrTypes) {
       if (supportedType == hdrType) {
         return true;
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/feedback/FeedbackService.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/feedback/FeedbackService.java
deleted file mode 100644
index 66a2547..0000000
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/feedback/FeedbackService.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dev.cobalt.feedback;
-
-import android.graphics.Bitmap;
-import dev.cobalt.util.UsedByNative;
-import java.util.HashMap;
-
-/** Java side implementation for starboard::android::shared::cobalt::FeedbackService. */
-public interface FeedbackService {
-  /**
-   * Sends the given product specific data to the GMS Feedback Service.
-   *
-   * <p>Implementations must annotate this method with @UsedByNative so Proguard doesn't remove it.
-   */
-  @SuppressWarnings("unused")
-  @UsedByNative
-  void sendFeedback(
-      HashMap<String, String> productSpecificData, String categoryTag, Bitmap screenshot);
-
-  void connect();
-
-  void disconnect();
-}
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/feedback/NoopFeedbackService.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/feedback/NoopFeedbackService.java
deleted file mode 100644
index 0c59c84..0000000
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/feedback/NoopFeedbackService.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dev.cobalt.feedback;
-
-import static dev.cobalt.util.Log.TAG;
-
-import android.graphics.Bitmap;
-import android.text.TextUtils;
-import dev.cobalt.util.Log;
-import dev.cobalt.util.UsedByNative;
-import java.util.HashMap;
-
-/** FeedbackService implementation that doesn't send any feedback. */
-public class NoopFeedbackService implements FeedbackService {
-  @Override
-  @SuppressWarnings("unused")
-  @UsedByNative
-  public void sendFeedback(
-      HashMap<String, String> productSpecificData, String categoryTag, Bitmap screenshot) {
-    Log.i(TAG, "Feedback product specific data:");
-    for (String key : productSpecificData.keySet()) {
-      Log.i(TAG, key + ": " + productSpecificData.get(key));
-    }
-    if (screenshot != null) {
-      Log.i(TAG, "Screenshot dimensions: " + screenshot.getWidth() + "x" + screenshot.getHeight());
-    }
-    if (!TextUtils.isEmpty(categoryTag)) {
-      Log.i(TAG, "Category tag: " + categoryTag);
-    }
-  }
-
-  @Override
-  public void connect() {}
-
-  @Override
-  public void disconnect() {}
-}
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/ArtworkLoader.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/ArtworkLoader.java
index 8fb4945..17dae73 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/ArtworkLoader.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/ArtworkLoader.java
@@ -18,7 +18,8 @@
 
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
 import android.util.Pair;
 import android.util.Size;
 import androidx.annotation.NonNull;
@@ -40,6 +41,7 @@
   @NonNull private volatile String currentArtworkUrl = "";
   private volatile Bitmap currentArtwork = null;
 
+  private final Handler handler = new Handler(Looper.getMainLooper());
   private final Callback callback;
   private final Size displaySize;
 
@@ -64,7 +66,7 @@
     }
 
     requestedArtworkUrl = url;
-    new DownloadArtworkTask().execute(url);
+    new DownloadArtworkThread(url, handler).start();
     return null;
   }
 
@@ -115,11 +117,19 @@
     }
   }
 
-  private class DownloadArtworkTask extends AsyncTask<String, Void, Pair<String, Bitmap>> {
+  private class DownloadArtworkThread extends Thread {
+
+    private final String url;
+    private final Handler handler;
+
+    DownloadArtworkThread(String url, Handler handler) {
+      super("ArtworkLoader");
+      this.url = url;
+      this.handler = handler;
+    }
 
     @Override
-    protected Pair<String, Bitmap> doInBackground(String... params) {
-      String url = params[0];
+    public void run() {
       Bitmap bitmap = null;
       HttpURLConnection conn = null;
       InputStream is = null;
@@ -151,17 +161,13 @@
         }
       }
 
-      return Pair.create(url, bitmap);
-    }
-
-    @Override
-    protected void onPostExecute(Pair<String, Bitmap> urlBitmapPair) {
-      onDownloadFinished(urlBitmapPair);
-    }
-
-    @Override
-    protected void onCancelled(Pair<String, Bitmap> urlBitmapPair) {
-      onDownloadFinished(urlBitmapPair);
+      final Pair<String, Bitmap> urlBitmapPair = Pair.create(url, bitmap);
+      handler.post(new Runnable() {
+        @Override
+        public void run() {
+          onDownloadFinished(urlBitmapPair);
+        }
+      });
     }
   }
 }
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
index f487c65..42c4e98 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
@@ -332,6 +332,33 @@
     }
   }
 
+  @SuppressWarnings("unused")
+  @UsedByNative
+  private static class CreateMediaCodecBridgeResult {
+    private MediaCodecBridge mMediaCodecBridge;
+    // Contains the error message when mMediaCodecBridge is null.
+    private String mErrorMessage;
+
+    @SuppressWarnings("unused")
+    @UsedByNative
+    private CreateMediaCodecBridgeResult() {
+      mMediaCodecBridge = null;
+      mErrorMessage = "";
+    }
+
+    @SuppressWarnings("unused")
+    @UsedByNative
+    private MediaCodecBridge mediaCodecBridge() {
+      return mMediaCodecBridge;
+    }
+
+    @SuppressWarnings("unused")
+    @UsedByNative
+    private String errorMessage() {
+      return mErrorMessage;
+    }
+  }
+
   private MediaCodecBridge(
       long nativeMediaCodecBridge,
       MediaCodec mediaCodec,
@@ -452,7 +479,7 @@
 
   @SuppressWarnings("unused")
   @UsedByNative
-  public static MediaCodecBridge createVideoMediaCodecBridge(
+  public static void createVideoMediaCodecBridge(
       long nativeMediaCodecBridge,
       String mime,
       boolean isSecure,
@@ -461,8 +488,10 @@
       int height,
       Surface surface,
       MediaCrypto crypto,
-      ColorInfo colorInfo) {
+      ColorInfo colorInfo,
+      CreateMediaCodecBridgeResult outCreateMediaCodecBridgeResult) {
     MediaCodec mediaCodec = null;
+    outCreateMediaCodecBridgeResult.mMediaCodecBridge = null;
 
     boolean findHDRDecoder = android.os.Build.VERSION.SDK_INT >= 24 && colorInfo != null;
     // On first pass, try to find a decoder with HDR if the color info is non-null.
@@ -478,16 +507,21 @@
       String decoderName = findVideoDecoderResult.name;
       if (decoderName.equals("") || findVideoDecoderResult.videoCapabilities == null) {
         Log.e(TAG, String.format("Failed to find decoder: %s, isSecure: %s", mime, isSecure));
-        return null;
+        outCreateMediaCodecBridgeResult.mErrorMessage =
+            String.format("Failed to find decoder: %s, isSecure: %s", mime, isSecure);
+        return;
       }
       Log.i(TAG, String.format("Creating \"%s\" decoder.", decoderName));
       mediaCodec = MediaCodec.createByCodecName(decoderName);
     } catch (Exception e) {
       Log.e(TAG, String.format("Failed to create MediaCodec: %s, isSecure: %s", mime, isSecure), e);
-      return null;
+      outCreateMediaCodecBridgeResult.mErrorMessage =
+          String.format("Failed to create MediaCodec: %s, isSecure: %s", mime, isSecure);
+      return;
     }
     if (mediaCodec == null) {
-      return null;
+      outCreateMediaCodecBridgeResult.mErrorMessage = "mediaCodec is null";
+      return;
     }
     MediaCodecBridge bridge =
         new MediaCodecBridge(
@@ -512,18 +546,28 @@
 
     int maxWidth = findVideoDecoderResult.videoCapabilities.getSupportedWidths().getUpper();
     int maxHeight = findVideoDecoderResult.videoCapabilities.getSupportedHeights().getUpper();
-    if (!bridge.configureVideo(mediaFormat, surface, crypto, 0, true, maxWidth, maxHeight)) {
+    if (!bridge.configureVideo(
+        mediaFormat,
+        surface,
+        crypto,
+        0,
+        true,
+        maxWidth,
+        maxHeight,
+        outCreateMediaCodecBridgeResult)) {
       Log.e(TAG, "Failed to configure video codec.");
       bridge.release();
-      return null;
+      // outCreateMediaCodecBridgeResult.mErrorMessage is set inside configureVideo() on error.
+      return;
     }
     if (!bridge.start()) {
       Log.e(TAG, "Failed to start video codec.");
       bridge.release();
-      return null;
+      outCreateMediaCodecBridgeResult.mErrorMessage = "Failed to start video codec";
+      return;
     }
 
-    return bridge;
+    outCreateMediaCodecBridgeResult.mMediaCodecBridge = bridge;
   }
 
   @SuppressWarnings("unused")
@@ -569,7 +613,7 @@
   @SuppressWarnings("unused")
   @UsedByNative
   private void stop() {
-    synchronized (mCallback) {
+    synchronized (this) {
       mNativeMediaCodecBridge = 0;
     }
     try {
@@ -772,7 +816,8 @@
       int flags,
       boolean allowAdaptivePlayback,
       int maxSupportedWidth,
-      int maxSupportedHeight) {
+      int maxSupportedHeight,
+      CreateMediaCodecBridgeResult outCreateMediaCodecBridgeResult) {
     try {
       // If adaptive playback is turned off by request, then treat it as
       // not supported.  Note that configureVideo is only called once
@@ -785,12 +830,12 @@
       if (mAdaptivePlaybackSupported) {
         // Since we haven't passed the properties of the stream we're playing
         // down to this level, from our perspective, we could potentially
-        // adapt up to 4k at any point.  We thus request 4k buffers up front,
-        // unless the decoder claims to not be able to do 4k, in which case
-        // we're ok, since we would've rejected a 4k stream when canPlayType
+        // adapt up to 8k at any point.  We thus request 8k buffers up front,
+        // unless the decoder claims to not be able to do 8k, in which case
+        // we're ok, since we would've rejected a 8k stream when canPlayType
         // was called, and then use those decoder values instead.
-        int maxWidth = Math.min(3840, maxSupportedWidth);
-        int maxHeight = Math.min(2160, maxSupportedHeight);
+        int maxWidth = Math.min(7680, maxSupportedWidth);
+        int maxHeight = Math.min(4320, maxSupportedHeight);
         format.setInteger(MediaFormat.KEY_MAX_WIDTH, maxWidth);
         format.setInteger(MediaFormat.KEY_MAX_HEIGHT, maxHeight);
       }
@@ -798,13 +843,21 @@
       mMediaCodec.configure(format, surface, crypto, flags);
       return true;
     } catch (IllegalArgumentException e) {
-      Log.e(TAG, "Cannot configure the video codec, wrong format or surface", e);
+      Log.e(TAG, "Cannot configure the video codec with IllegalArgumentException: ", e);
+      outCreateMediaCodecBridgeResult.mErrorMessage =
+          "Cannot configure the video codec with IllegalArgumentException: " + e.toString();
     } catch (IllegalStateException e) {
-      Log.e(TAG, "Cannot configure the video codec", e);
+      Log.e(TAG, "Cannot configure the video codec with IllegalStateException: ", e);
+      outCreateMediaCodecBridgeResult.mErrorMessage =
+          "Cannot configure the video codec with IllegalStateException: " + e.toString();
     } catch (MediaCodec.CryptoException e) {
-      Log.e(TAG, "Cannot configure the video codec: DRM error", e);
+      Log.e(TAG, "Cannot configure the video codec with CryptoException: ", e);
+      outCreateMediaCodecBridgeResult.mErrorMessage =
+          "Cannot configure the video codec with CryptoException: " + e.toString();
     } catch (Exception e) {
-      Log.e(TAG, "Cannot configure the video codec", e);
+      Log.e(TAG, "Cannot configure the video codec with Exception: ", e);
+      outCreateMediaCodecBridgeResult.mErrorMessage =
+          "Cannot configure the video codec with Exception: " + e.toString();
     }
     return false;
   }
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaDrmBridge.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaDrmBridge.java
index 4e1586d..b3b8300 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaDrmBridge.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaDrmBridge.java
@@ -29,6 +29,7 @@
 import android.media.NotProvisionedException;
 import android.media.UnsupportedSchemeException;
 import android.os.Build;
+import android.util.Base64;
 import androidx.annotation.RequiresApi;
 import dev.cobalt.coat.CobaltHttpHelper;
 import dev.cobalt.util.Log;
@@ -347,6 +348,21 @@
   }
 
   @UsedByNative
+  byte[] getMetricsInBase64() {
+    if (Build.VERSION.SDK_INT < 28) {
+      return null;
+    }
+    byte[] metrics;
+    try {
+      metrics = mMediaDrm.getPropertyByteArray("metrics");
+    } catch (Exception e) {
+      Log.e(TAG, "Failed to retrieve DRM Metrics.");
+      return null;
+    }
+    return Base64.encode(metrics, Base64.NO_PADDING | Base64.NO_WRAP | Base64.URL_SAFE);
+  }
+
+  @UsedByNative
   MediaCrypto getMediaCrypto() {
     return mMediaCrypto;
   }
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java
index 0274811..1e39d63 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java
@@ -35,8 +35,9 @@
 import android.os.Message;
 import android.view.Choreographer;
 import android.view.Choreographer.FrameCallback;
-import android.view.WindowManager;
+import android.view.Display;
 import androidx.annotation.RequiresApi;
+import dev.cobalt.util.DisplayUtil;
 import dev.cobalt.util.UsedByNative;
 
 /** Makes a best effort to adjust frame release timestamps for a smoother visual result. */
@@ -221,9 +222,9 @@
   }
 
   private static double getDefaultDisplayRefreshRate(Context context) {
-    WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-    return manager.getDefaultDisplay() != null
-        ? manager.getDefaultDisplay().getRefreshRate()
+    Display defaultDisplay = DisplayUtil.getDefaultDisplay(context);
+    return defaultDisplay != null
+        ?  defaultDisplay.getRefreshRate()
         : DISPLAY_REFRESH_RATE_UNKNOWN;
   }
 
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/util/DisplayUtil.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/util/DisplayUtil.java
index 16f2b46..6836656 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/util/DisplayUtil.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/util/DisplayUtil.java
@@ -15,9 +15,13 @@
 package dev.cobalt.util;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.util.DisplayMetrics;
 import android.util.Size;
+import android.view.Display;
 import android.view.WindowManager;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 /** Utility functions for querying display attributes. */
 public class DisplayUtil {
@@ -25,6 +29,34 @@
   private DisplayUtil() {}
 
   /**
+   * Returns the default display associated with a context.
+   */
+  @Nullable
+  public static Display getDefaultDisplay(Context context) {
+    if (context == null) {
+      return null;
+    }
+    if (android.os.Build.VERSION.SDK_INT >= 30) {
+      return getDefaultDisplayV30(context);
+    } else {
+      return getDefaultDisplayDeprecated(context);
+    }
+  }
+
+  @Nullable
+  @SuppressWarnings("deprecation")
+  private static Display getDefaultDisplayDeprecated(Context context) {
+    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+    return (wm == null) ? null : wm.getDefaultDisplay();
+  }
+
+  @Nullable
+  @RequiresApi(30)
+  private static Display getDefaultDisplayV30(Context context) {
+    return context.getDisplay();
+  }
+
+  /**
    * Returns the size of the physical display size in pixels.
    *
    * <p>This differs from {@link #getSystemDisplaySize(Context)} because it only uses
@@ -72,10 +104,10 @@
   private static DisplayMetrics cachedDisplayMetrics = null;
 
   private static DisplayMetrics getDisplayMetrics(Context context) {
+    Resources.getSystem().getDisplayMetrics();
     if (cachedDisplayMetrics == null) {
       cachedDisplayMetrics = new DisplayMetrics();
-      ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
-          .getDefaultDisplay().getRealMetrics(cachedDisplayMetrics);
+      getDefaultDisplay(context).getRealMetrics(cachedDisplayMetrics);
     }
     return cachedDisplayMetrics;
   }
diff --git a/src/starboard/android/apk/build.gradle b/src/starboard/android/apk/build.gradle
index c21ed86..27edbf5 100644
--- a/src/starboard/android/apk/build.gradle
+++ b/src/starboard/android/apk/build.gradle
@@ -20,7 +20,7 @@
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.6.1'
+        classpath 'com.android.tools.build:gradle:3.6.3'
 
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
diff --git a/src/starboard/android/apk/gradle.properties b/src/starboard/android/apk/gradle.properties
index d9f30ec..47995b5 100644
--- a/src/starboard/android/apk/gradle.properties
+++ b/src/starboard/android/apk/gradle.properties
@@ -27,6 +27,13 @@
 android.useAndroidX=true
 org.gradle.jvmargs=-Xmx4g
 
+# Android Studio plugin 3.0 adds the testOnly=1 attribute to the APK manifest
+# which means that it can't be installed without the '-t' parameter passed to
+# 'adb install'. We want CoAT to be widely usable for testing, so we override
+# that attribute to be false.
+# See: https://commonsware.com/blog/2017/10/31/android-studio-3p0-flag-test-only.html
+android.injected.testOnly=false
+
 # When configured, Gradle will run in incubating parallel mode.
 # This option should only be used with decoupled projects. More details, visit
 # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
diff --git a/src/starboard/android/arm/gyp_configuration.py b/src/starboard/android/arm/gyp_configuration.py
index ca56491..0fcdd2a 100644
--- a/src/starboard/android/arm/gyp_configuration.py
+++ b/src/starboard/android/arm/gyp_configuration.py
@@ -20,4 +20,4 @@
   return shared_configuration.AndroidConfiguration(
       'android-arm',
       'armeabi-v7a',
-      sabi_json_path='starboard/sabi/arm/softfp/sabi.json')
+      sabi_json_path='starboard/sabi/arm/softfp/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/android/arm64/gyp_configuration.py b/src/starboard/android/arm64/gyp_configuration.py
index 243d3a1..2e21425 100644
--- a/src/starboard/android/arm64/gyp_configuration.py
+++ b/src/starboard/android/arm64/gyp_configuration.py
@@ -20,4 +20,4 @@
   return shared_configuration.AndroidConfiguration(
       'android-arm64',
       'arm64-v8a',
-      sabi_json_path='starboard/sabi/arm64/sabi.json')
+      sabi_json_path='starboard/sabi/arm64/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/android/arm64/vulkan/gyp_configuration.py b/src/starboard/android/arm64/vulkan/gyp_configuration.py
index 8fb4bb5..1c1df77 100644
--- a/src/starboard/android/arm64/vulkan/gyp_configuration.py
+++ b/src/starboard/android/arm64/vulkan/gyp_configuration.py
@@ -20,4 +20,4 @@
   return shared_configuration.AndroidConfiguration(
       'android-arm64-vulkan',
       'arm64-v8a',
-      sabi_json_path='starboard/sabi/arm64/sabi.json')
+      sabi_json_path='starboard/sabi/arm64/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/android/shared/accessibility_set_captions_enabled.cc b/src/starboard/android/shared/accessibility_set_captions_enabled.cc
index f39ad20..3bd95ba 100644
--- a/src/starboard/android/shared/accessibility_set_captions_enabled.cc
+++ b/src/starboard/android/shared/accessibility_set_captions_enabled.cc
@@ -16,6 +16,5 @@
 #include "starboard/configuration.h"
 
 bool SbAccessibilitySetCaptionsEnabled(bool enabled) {
-  SB_UNREFERENCED_PARAMETER(enabled);
   return false;
 }
diff --git a/src/starboard/android/shared/application_android.cc b/src/starboard/android/shared/application_android.cc
index 5048e4d..e8fab42 100644
--- a/src/starboard/android/shared/application_android.cc
+++ b/src/starboard/android/shared/application_android.cc
@@ -137,7 +137,6 @@
 }
 
 SbWindow ApplicationAndroid::CreateWindow(const SbWindowOptions* options) {
-  SB_UNREFERENCED_PARAMETER(options);
   if (SbWindowIsValid(window_)) {
     return kSbWindowInvalid;
   }
@@ -415,7 +414,7 @@
 Java_dev_cobalt_coat_KeyboardInputConnection_nativeHasOnScreenKeyboard(
     JniEnvExt* env,
     jobject unused_this) {
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
   return SbWindowOnScreenKeyboardIsSupported() ? JNI_TRUE : JNI_FALSE;
 #elif SB_HAS(ON_SCREEN_KEYBOARD)
   return JNI_TRUE;
@@ -424,8 +423,7 @@
 #endif
 }
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 
 void ApplicationAndroid::SbWindowShowOnScreenKeyboard(SbWindow window,
                                                       const char* input_text,
@@ -518,7 +516,7 @@
   return;
 }
 
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
 
 bool ApplicationAndroid::OnSearchRequested() {
diff --git a/src/starboard/android/shared/audio_sink_min_required_frames_tester.cc b/src/starboard/android/shared/audio_sink_min_required_frames_tester.cc
index 6276641..ac5815e 100644
--- a/src/starboard/android/shared/audio_sink_min_required_frames_tester.cc
+++ b/src/starboard/android/shared/audio_sink_min_required_frames_tester.cc
@@ -168,8 +168,6 @@
 void MinRequiredFramesTester::ConsumeFramesFunc(int frames_consumed,
                                                 SbTime frames_consumed_at,
                                                 void* context) {
-  SB_UNREFERENCED_PARAMETER(frames_consumed_at);
-
   MinRequiredFramesTester* tester =
       static_cast<MinRequiredFramesTester*>(context);
   SB_DCHECK(tester);
diff --git a/src/starboard/android/shared/audio_track_audio_sink_type.cc b/src/starboard/android/shared/audio_track_audio_sink_type.cc
index bcda615..44dffc8 100644
--- a/src/starboard/android/shared/audio_track_audio_sink_type.cc
+++ b/src/starboard/android/shared/audio_track_audio_sink_type.cc
@@ -85,7 +85,7 @@
     int frames_per_channel,
     int preferred_buffer_size_in_bytes,
     SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-    SbAudioSinkConsumeFramesFunc consume_frame_func,
+    ConsumeFramesFunc consume_frames_func,
     void* context)
     : type_(type),
       channels_(channels),
@@ -94,7 +94,7 @@
       frame_buffer_(frame_buffers[0]),
       frames_per_channel_(frames_per_channel),
       update_source_status_func_(update_source_status_func),
-      consume_frame_func_(consume_frame_func),
+      consume_frames_func_(consume_frames_func),
       context_(context),
       last_playback_head_position_(0),
       j_audio_track_bridge_(NULL),
@@ -104,7 +104,7 @@
       playback_rate_(1.0f),
       written_frames_(0) {
   SB_DCHECK(update_source_status_func_);
-  SB_DCHECK(consume_frame_func_);
+  SB_DCHECK(consume_frames_func_);
   SB_DCHECK(frame_buffer_);
   SB_DCHECK(SbAudioSinkIsAudioSampleTypeSupported(sample_type));
 
@@ -236,7 +236,7 @@
 
       if (frames_consumed != 0) {
         SB_DCHECK(frames_consumed >= 0);
-        consume_frame_func_(frames_consumed, frames_consumed_at, context_);
+        consume_frames_func_(frames_consumed, frames_consumed_at, context_);
         written_frames_ -= frames_consumed;
       }
     }
@@ -414,7 +414,7 @@
     SbAudioSinkFrameBuffers frame_buffers,
     int frames_per_channel,
     SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-    SbAudioSinkConsumeFramesFunc consume_frames_func,
+    SbAudioSinkPrivate::ConsumeFramesFunc consume_frames_func,
     SbAudioSinkPrivate::ErrorFunc error_func,
     void* context) {
   int min_required_frames = SbAudioSinkGetMinBufferSizeInFrames(
diff --git a/src/starboard/android/shared/audio_track_audio_sink_type.h b/src/starboard/android/shared/audio_track_audio_sink_type.h
index 71f5c55..1a8cb37 100644
--- a/src/starboard/android/shared/audio_track_audio_sink_type.h
+++ b/src/starboard/android/shared/audio_track_audio_sink_type.h
@@ -51,9 +51,9 @@
       SbAudioSinkFrameBuffers frame_buffers,
       int frames_per_channel,
       SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-      SbAudioSinkConsumeFramesFunc consume_frames_func,
+      SbAudioSinkPrivate::ConsumeFramesFunc consume_frames_func,
       SbAudioSinkPrivate::ErrorFunc error_func,
-      void* context);
+      void* context) override;
 
   bool IsValid(SbAudioSink audio_sink) override {
     return audio_sink != kSbAudioSinkInvalid && audio_sink->IsType(this);
@@ -91,7 +91,7 @@
       int frames_per_channel,
       int preferred_buffer_size,
       SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-      SbAudioSinkConsumeFramesFunc consume_frame_func,
+      ConsumeFramesFunc consume_frames_func,
       void* context);
   ~AudioTrackAudioSink() override;
 
@@ -115,7 +115,7 @@
   void* frame_buffer_;
   int frames_per_channel_;
   SbAudioSinkUpdateSourceStatusFunc update_source_status_func_;
-  SbAudioSinkConsumeFramesFunc consume_frame_func_;
+  ConsumeFramesFunc consume_frames_func_;
   void* context_;
   int last_playback_head_position_;
   jobject j_audio_track_bridge_;
diff --git a/src/starboard/android/shared/cobalt/android.cc b/src/starboard/android/shared/cobalt/android.cc
deleted file mode 100644
index e9e10fa..0000000
--- a/src/starboard/android/shared/cobalt/android.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/android/shared/cobalt/android.h"
-
-namespace cobalt {
-namespace webapi_extension {
-
-Android::Android(const scoped_refptr<::cobalt::dom::Window>& /*window*/) {
-  feedback_service_ = new FeedbackService();
-}
-
-void Android::TraceMembers(script::Tracer* tracer) {
-  tracer->Trace(feedback_service_);
-}
-
-Android::~Android() {}
-
-}  // namespace webapi_extension
-}  // namespace cobalt
diff --git a/src/starboard/android/shared/cobalt/android.h b/src/starboard/android/shared/cobalt/android.h
deleted file mode 100644
index b21d533..0000000
--- a/src/starboard/android/shared/cobalt/android.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef STARBOARD_ANDROID_SHARED_COBALT_ANDROID_H_
-#define STARBOARD_ANDROID_SHARED_COBALT_ANDROID_H_
-
-#include "cobalt/dom/window.h"
-#include "cobalt/script/wrappable.h"
-#include "starboard/android/shared/cobalt/feedback_service.h"
-
-namespace cobalt {
-namespace webapi_extension {
-
-class Android : public ::cobalt::script::Wrappable {
- public:
-  explicit Android(const scoped_refptr<::cobalt::dom::Window>& window);
-
-  const scoped_refptr<FeedbackService>& feedback_service() const {
-    return feedback_service_;
-  }
-
-  DEFINE_WRAPPABLE_TYPE(Android);
-  void TraceMembers(script::Tracer* tracer) override;
-
- private:
-  ~Android() override;
-
-  scoped_refptr<FeedbackService> feedback_service_;
-
-  DISALLOW_COPY_AND_ASSIGN(Android);
-};
-
-}  // namespace webapi_extension
-}  // namespace cobalt
-
-#endif  // STARBOARD_ANDROID_SHARED_COBALT_ANDROID_H_
diff --git a/src/starboard/android/shared/cobalt/android.idl b/src/starboard/android/shared/cobalt/android.idl
deleted file mode 100644
index 18e71e7..0000000
--- a/src/starboard/android/shared/cobalt/android.idl
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// The Cobalt Web Extension for Android.
-interface Android {
-  readonly attribute FeedbackService feedbackService;
-};
diff --git a/src/starboard/android/shared/cobalt/android_webapi_extension.cc b/src/starboard/android/shared/cobalt/android_webapi_extension.cc
deleted file mode 100644
index a1d699e..0000000
--- a/src/starboard/android/shared/cobalt/android_webapi_extension.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "cobalt/browser/webapi_extension.h"
-
-#include "base/compiler_specific.h"
-#include "cobalt/script/global_environment.h"
-#include "starboard/android/shared/cobalt/android.h"
-
-namespace cobalt {
-namespace browser {
-
-base::Optional<std::string> GetWebAPIExtensionObjectPropertyName() {
-  return std::string("android");
-}
-
-scoped_refptr<::cobalt::script::Wrappable> CreateWebAPIExtensionObject(
-    const scoped_refptr<::cobalt::dom::Window>& window,
-    ::cobalt::script::GlobalEnvironment* global_environment) {
-  SB_UNREFERENCED_PARAMETER(global_environment);
-
-  return scoped_refptr<::cobalt::script::Wrappable>(
-      new webapi_extension::Android(window));
-}
-
-}  // namespace browser
-}  // namespace cobalt
diff --git a/src/starboard/android/shared/cobalt/android_webapi_extension.gyp b/src/starboard/android/shared/cobalt/android_webapi_extension.gyp
deleted file mode 100644
index f3fd2e0..0000000
--- a/src/starboard/android/shared/cobalt/android_webapi_extension.gyp
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-{
-  'targets': [
-    {
-      'target_name': 'android_webapi_extension',
-      'type': 'static_library',
-      'sources': [
-        'android.h',
-        'android.cc',
-        'android_webapi_extension.cc',
-        'feedback_service.h',
-        'feedback_service.cc',
-      ],
-      'dependencies': [
-        '<(DEPTH)/base/base.gyp:base',
-        '<(DEPTH)/cobalt/dom/dom.gyp:dom',
-        '<(DEPTH)/cobalt/script/script.gyp:script',
-      ],
-    },
-  ],
-}
diff --git a/src/starboard/android/shared/cobalt/configuration.gypi b/src/starboard/android/shared/cobalt/configuration.gypi
index ef81612..c374599 100644
--- a/src/starboard/android/shared/cobalt/configuration.gypi
+++ b/src/starboard/android/shared/cobalt/configuration.gypi
@@ -21,43 +21,15 @@
     'custom_media_session_client': 1,
     'enable_account_manager': 1,
 
-    'cobalt_enable_quic': 0,
-
-    # Some Android devices do not advertise their support for
-    # EGL_SWAP_BEHAVIOR_PRESERVED_BIT properly, so, we play it safe and disable
-    # relying on it for Android.
-    'render_dirty_region_only': 0,
-
     # The 'android_system' font package installs only minimal fonts, with a
     # fonts.xml referencing the superset of font files we expect to find on any
     # Android platform. The Android SbFileOpen implementation falls back to
     # system fonts when it can't find the font file in the cobalt content.
     'cobalt_font_package': 'android_system',
 
-    # On Android, we almost never want to actually terminate the process, so
-    # instead indicate that we would instead like to be suspended when users
-    # initiate an "exit".
-    'cobalt_user_on_exit_strategy': 'suspend',
-
-    # Switch Android's SurfaceFlinger queue to "async mode" so that we don't
-    # queue up rendered frames which would interfere with frame timing and
-    # more importantly lead to input latency.
-    'cobalt_egl_swap_interval': 0,
-
     # Platform-specific implementations to compile into cobalt.
     'cobalt_platform_dependencies': [
       '<(DEPTH)/starboard/android/shared/cobalt/cobalt_platform.gyp:cobalt_platform',
     ],
-
-    # Platform-specific interfaces to inject into Cobalt's JavaScript 'window'
-    # global object.
-    'cobalt_webapi_extension_source_idl_files': [
-      'android.idl',
-      'feedback_service.idl',
-    ],
-
-    # Platform-specific IDL interface implementations.
-    'cobalt_webapi_extension_gyp_target':
-    '<(DEPTH)/starboard/android/shared/cobalt/android_webapi_extension.gyp:android_webapi_extension',
   },
 }
diff --git a/src/starboard/android/shared/cobalt/configuration.py b/src/starboard/android/shared/cobalt/configuration.py
index 8fac1a4..96c11fe 100644
--- a/src/starboard/android/shared/cobalt/configuration.py
+++ b/src/starboard/android/shared/cobalt/configuration.py
@@ -73,4 +73,14 @@
           # run it on Android platforms.
           'StressTest.TooManyTextures',
       ],
+      'zip_unittests': [
+          # These tests, and zipping in general, rely on the ability to iterate
+          # recursively to find all of the files that should be zipped. This is
+          # explicitly not supported for the asset directory on Android. If this
+          # functionality is needed at some point, enabling these tests should
+          # be revisited.
+          #
+          # See: starboard/android/shared/file_internal.cc.
+          'ZipTest.Zip*',
+      ],
   }
diff --git a/src/starboard/android/shared/cobalt/feedback_service.cc b/src/starboard/android/shared/cobalt/feedback_service.cc
deleted file mode 100644
index c17307d..0000000
--- a/src/starboard/android/shared/cobalt/feedback_service.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/android/shared/cobalt/feedback_service.h"
-
-#include "starboard/android/shared/jni_env_ext.h"
-#include "starboard/android/shared/jni_utils.h"
-
-namespace cobalt {
-namespace webapi_extension {
-
-void FeedbackService::SendFeedback(
-    const script::ValueHandleHolder& product_specific_data,
-    const std::string& category_tag,
-    script::ExceptionState* exception_state) {
-  const script::Handle<script::ArrayBuffer> empty_array_buffer;
-  SendFeedback(product_specific_data, category_tag, empty_array_buffer,
-               exception_state);
-}
-
-void FeedbackService::SendFeedback(
-    const script::ValueHandleHolder& product_specific_data,
-    const std::string& category_tag,
-    const script::Handle<script::ArrayBuffer>& screenshot_data,
-    script::ExceptionState* exception_state) {
-  using starboard::android::shared::ScopedLocalJavaRef;
-  using starboard::android::shared::JniEnvExt;
-
-  std::unordered_map<std::string, std::string> product_specific_data_map =
-      script::ConvertSimpleObjectToMap(product_specific_data, exception_state);
-
-  JniEnvExt* env = JniEnvExt::Get();
-
-  // Convert the unordered map of product specific data to a hashmap in JNI.
-  ScopedLocalJavaRef<jobject> product_specific_data_hash_map(
-      env->NewObjectOrAbort("java/util/HashMap", "(I)V",
-                            product_specific_data_map.size()));
-
-  ScopedLocalJavaRef<jstring> key;
-  ScopedLocalJavaRef<jstring> value;
-
-  for (const auto& data : product_specific_data_map) {
-    key.Reset(env->NewStringStandardUTFOrAbort(data.first.c_str()));
-    value.Reset(env->NewStringStandardUTFOrAbort(data.second.c_str()));
-
-    env->CallObjectMethodOrAbort(
-        product_specific_data_hash_map.Get(), "put",
-        "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", key.Get(),
-        value.Get());
-  }
-
-  ScopedLocalJavaRef<jstring> category_tag_string;
-  category_tag_string.Reset(
-      env->NewStringStandardUTFOrAbort(category_tag.c_str()));
-
-  // Convert the screenshot to a byte array in JNI.
-  ScopedLocalJavaRef<jbyteArray> screenshot_byte_array;
-  if (!screenshot_data.IsEmpty()) {
-    screenshot_byte_array.Reset(env->NewByteArrayFromRaw(
-        reinterpret_cast<const jbyte*>(screenshot_data->Data()),
-        screenshot_data->ByteLength()));
-    env->AbortOnException();
-  }
-
-  env->CallStarboardVoidMethodOrAbort(
-      "sendFeedback", "(Ljava/util/HashMap;Ljava/lang/String;[B)V",
-      product_specific_data_hash_map.Get(), category_tag_string.Get(),
-      screenshot_byte_array.Get());
-}
-
-}  // namespace webapi_extension
-}  // namespace cobalt
diff --git a/src/starboard/android/shared/cobalt/feedback_service.h b/src/starboard/android/shared/cobalt/feedback_service.h
deleted file mode 100644
index 270cf16..0000000
--- a/src/starboard/android/shared/cobalt/feedback_service.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef STARBOARD_ANDROID_SHARED_COBALT_FEEDBACK_SERVICE_H_
-#define STARBOARD_ANDROID_SHARED_COBALT_FEEDBACK_SERVICE_H_
-
-#include <string>
-
-#include "cobalt/script/array_buffer.h"
-#include "cobalt/script/exception_state.h"
-#include "cobalt/script/value_handle.h"
-#include "cobalt/script/wrappable.h"
-
-namespace cobalt {
-namespace webapi_extension {
-
-class FeedbackService : public ::cobalt::script::Wrappable {
- public:
-  void SendFeedback(const script::ValueHandleHolder& product_specific_data,
-                    const std::string& category_tag,
-                    script::ExceptionState* exception_state);
-
-  void SendFeedback(const script::ValueHandleHolder& product_specific_data,
-                    const std::string& category_tag,
-                    const script::Handle<script::ArrayBuffer>& screenshot_data,
-                    script::ExceptionState* exception_state);
-
-  FeedbackService() = default;
-  FeedbackService(const FeedbackService&) = delete;
-  FeedbackService& operator=(const FeedbackService&) = delete;
-
-  DEFINE_WRAPPABLE_TYPE(FeedbackService);
-};
-
-}  // namespace webapi_extension
-}  // namespace cobalt
-
-#endif  // STARBOARD_ANDROID_SHARED_COBALT_FEEDBACK_SERVICE_H_
diff --git a/src/starboard/android/shared/cobalt/feedback_service.idl b/src/starboard/android/shared/cobalt/feedback_service.idl
deleted file mode 100644
index b4c722a..0000000
--- a/src/starboard/android/shared/cobalt/feedback_service.idl
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// The send feedback report service.
-interface FeedbackService {
-  // Send feedback.
-  [RaisesException] void sendFeedback(any productSpecificData,
-                                      optional DOMString categoryTag = "",
-                                      optional ArrayBuffer screenshotData);
-};
diff --git a/src/starboard/android/shared/configuration.cc b/src/starboard/android/shared/configuration.cc
index 374d0ed..c52e26f 100644
--- a/src/starboard/android/shared/configuration.cc
+++ b/src/starboard/android/shared/configuration.cc
@@ -24,10 +24,16 @@
 namespace {
 
 const char* CobaltUserOnExitStrategy() {
+  // On Android, we almost never want to actually terminate the process, so
+  // instead indicate that we would instead like to be suspended when users
+  // initiate an "exit".
   return "suspend";
 }
 
 int CobaltEglSwapInterval() {
+  // Switch Android's SurfaceFlinger queue to "async mode" so that we don't
+  // queue up rendered frames which would interfere with frame timing and
+  // more importantly lead to input latency.
   return 0;
 }
 
diff --git a/src/starboard/android/shared/configuration_constants.cc b/src/starboard/android/shared/configuration_constants.cc
index a70e4db..bbf77e7 100644
--- a/src/starboard/android/shared/configuration_constants.cc
+++ b/src/starboard/android/shared/configuration_constants.cc
@@ -52,9 +52,6 @@
 // Allow ac3 and ec3 support
 const bool kSbHasAc3Audio = true;
 
-// Specifies whether this platform updates audio frames asynchronously.
-const bool kSbHasAsyncAudioFramesReporting = true;
-
 // Specifies whether this platform has webm/vp9 support.  This should be set to
 // non-zero on platforms with webm/vp9 support.
 const bool kSbHasMediaWebmVp9Support = true;
diff --git a/src/starboard/android/shared/drm_system.cc b/src/starboard/android/shared/drm_system.cc
index 984fe64..e196128 100644
--- a/src/starboard/android/shared/drm_system.cc
+++ b/src/starboard/android/shared/drm_system.cc
@@ -291,6 +291,27 @@
   return kSuccess;
 }
 
+const void* DrmSystem::GetMetrics(int* size) {
+  JniEnvExt* env = JniEnvExt::Get();
+  jbyteArray j_metrics = static_cast<jbyteArray>(env->CallObjectMethodOrAbort(
+      j_media_drm_bridge_, "getMetricsInBase64", "()[B"));
+
+  if (!j_metrics) {
+    *size = 0;
+    return nullptr;
+  }
+
+  jbyte* metrics_elements = env->GetByteArrayElements(j_metrics, NULL);
+  jsize metrics_size = env->GetArrayLength(j_metrics);
+  SB_DCHECK(metrics_elements);
+
+  metrics_.assign(metrics_elements, metrics_elements + metrics_size);
+
+  env->ReleaseByteArrayElements(j_metrics, metrics_elements, JNI_ABORT);
+  *size = static_cast<int>(metrics_.size());
+  return metrics_.data();
+}
+
 void DrmSystem::CallUpdateRequestCallback(int ticket,
                                           SbDrmSessionRequestType request_type,
                                           const void* session_id,
diff --git a/src/starboard/android/shared/drm_system.h b/src/starboard/android/shared/drm_system.h
index 9bdd875..19b4bfe 100644
--- a/src/starboard/android/shared/drm_system.h
+++ b/src/starboard/android/shared/drm_system.h
@@ -25,6 +25,7 @@
 
 #include "starboard/common/log.h"
 #include "starboard/common/mutex.h"
+#include "starboard/types.h"
 
 namespace starboard {
 namespace android {
@@ -54,10 +55,8 @@
   void UpdateServerCertificate(int ticket,
                                const void* certificate,
                                int certificate_size) override {
-    SB_UNREFERENCED_PARAMETER(ticket);
-    SB_UNREFERENCED_PARAMETER(certificate);
-    SB_UNREFERENCED_PARAMETER(certificate_size);
   }
+  const void* GetMetrics(int* size) override;
 
   jobject GetMediaCrypto() const { return j_media_crypto_; }
   void CallUpdateRequestCallback(int ticket,
@@ -93,6 +92,8 @@
   Mutex mutex_;
   std::unordered_map<std::string, std::vector<SbDrmKeyId> > cached_drm_key_ids_;
   bool hdcp_lost_;
+
+  std::vector<uint8_t> metrics_;
 };
 
 }  // namespace shared
diff --git a/src/starboard/android/shared/gyp_configuration.py b/src/starboard/android/shared/gyp_configuration.py
index 52c4c5e..b0eef56 100644
--- a/src/starboard/android/shared/gyp_configuration.py
+++ b/src/starboard/android/shared/gyp_configuration.py
@@ -70,7 +70,7 @@
                platform,
                android_abi,
                asan_enabled_by_default=False,
-               sabi_json_path=None):
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     super(AndroidConfiguration, self).__init__(platform,
                                                asan_enabled_by_default)
     self._target_toolchain = None
@@ -108,13 +108,11 @@
             'starboard/android/shared/platform_deploy.gypi',
         'javascript_engine':
             'v8',
-        'cobalt_enable_jit':
-            1,
     })
     return variables
 
   def GetDeployPathPatterns(self):
-    """example src/out/android-arm64/devel/cobalt.apk"""
+    # example src/out/android-arm64/devel/cobalt.apk
     return ['*.apk']
 
   def GetGeneratorVariables(self, configuration):
@@ -144,7 +142,7 @@
 
     return env_variables
 
-  def GetTargetToolchain(self):
+  def GetTargetToolchain(self, **kwargs):
     if not self._target_toolchain:
       tool_prefix = os.path.join(sdk_utils.GetNdkPath(), 'toolchains', 'llvm',
                                  'prebuilt', 'linux-x86_64', 'bin', '')
@@ -244,7 +242,7 @@
       ]
     return self._target_toolchain
 
-  def GetHostToolchain(self):
+  def GetHostToolchain(self, **kwargs):
     if not self._host_toolchain:
       if not hasattr(self, 'host_compiler_environment'):
         self.host_compiler_environment = build.GetHostCompilerEnvironment(
@@ -327,6 +325,11 @@
           # This test is failing because localhost is not defined for IPv6 in
           # /etc/hosts.
           'SbSocketAddressTypes/SbSocketResolveTest.Localhost/1',
+          # SbDirectory has problems with empty Asset dirs. See b/154881065.
+          'SbDirectoryCanOpenTest.SunnyDayStaticContent',
+          'SbDirectoryGetNextTest.SunnyDayStaticContent',
+          'SbDirectoryOpenTest.SunnyDayStaticContent',
+          'SbFileGetPathInfoTest.WorksOnStaticContentDirectories',
       ],
   }
 
diff --git a/src/starboard/android/shared/jni_env_ext.h b/src/starboard/android/shared/jni_env_ext.h
index a40f499..92d7b73 100644
--- a/src/starboard/android/shared/jni_env_ext.h
+++ b/src/starboard/android/shared/jni_env_ext.h
@@ -179,7 +179,8 @@
 #define X(_jtype, _jname)                                                      \
   _jtype Get##_jname##FieldOrAbort(jobject obj, const char* name,              \
                                    const char* sig) {                          \
-    _jtype result = Get##_jname##Field(obj, GetFieldIDOrAbort(obj, name, sig));\
+    _jtype result =                                                            \
+        Get##_jname##Field(obj, GetFieldIDOrAbort(obj, name, sig));            \
     AbortOnException();                                                        \
     return result;                                                             \
   }                                                                            \
@@ -209,7 +210,7 @@
   }                                                                            \
                                                                                \
   _jtype CallStarboard##_jname##MethodOrAbort(const char* name,                \
-                                             const char* sig, ...) {           \
+                                              const char* sig, ...) {          \
     va_list argp;                                                              \
     va_start(argp, sig);                                                       \
     jobject obj = GetStarboardBridge();                                        \
diff --git a/src/starboard/android/shared/media_codec_bridge.cc b/src/starboard/android/shared/media_codec_bridge.cc
index c3c599d..c4f070a 100644
--- a/src/starboard/android/shared/media_codec_bridge.cc
+++ b/src/starboard/android/shared/media_codec_bridge.cc
@@ -14,6 +14,8 @@
 
 #include "starboard/android/shared/media_codec_bridge.h"
 
+#include "starboard/format_string.h"
+
 namespace starboard {
 namespace android {
 namespace shared {
@@ -178,9 +180,13 @@
     jobject j_surface,
     jobject j_media_crypto,
     const SbMediaColorMetadata* color_metadata,
-    bool require_software_codec) {
+    bool require_software_codec,
+    std::string* error_message) {
+  SB_DCHECK(error_message);
+
   const char* mime = SupportedVideoCodecToMimeType(video_codec);
   if (!mime) {
+    *error_message = FormatString("Unsupported mime for codec %d", video_codec);
     return scoped_ptr<MediaCodecBridge>(NULL);
   }
   JniEnvExt* env = JniEnvExt::Get();
@@ -213,19 +219,34 @@
     }
   }
 
+  ScopedLocalJavaRef<jobject> j_create_media_codec_bridge_result(
+      env->NewObjectOrAbort(
+          "dev/cobalt/media/MediaCodecBridge$CreateMediaCodecBridgeResult",
+          "()V"));
+
   scoped_ptr<MediaCodecBridge> native_media_codec_bridge(
       new MediaCodecBridge(handler));
-  jobject j_media_codec_bridge = env->CallStaticObjectMethodOrAbort(
+  env->CallStaticVoidMethodOrAbort(
       "dev/cobalt/media/MediaCodecBridge", "createVideoMediaCodecBridge",
       "(JLjava/lang/String;ZZIILandroid/view/Surface;"
       "Landroid/media/MediaCrypto;"
-      "Ldev/cobalt/media/MediaCodecBridge$ColorInfo;)"
-      "Ldev/cobalt/media/MediaCodecBridge;",
+      "Ldev/cobalt/media/MediaCodecBridge$ColorInfo;"
+      "Ldev/cobalt/media/MediaCodecBridge$CreateMediaCodecBridgeResult;)"
+      "V",
       reinterpret_cast<jlong>(native_media_codec_bridge.get()), j_mime.Get(),
       !!j_media_crypto, require_software_codec, width, height, j_surface,
-      j_media_crypto, j_color_info.Get());
+      j_media_crypto, j_color_info.Get(),
+      j_create_media_codec_bridge_result.Get());
+
+  jobject j_media_codec_bridge = env->CallObjectMethodOrAbort(
+      j_create_media_codec_bridge_result.Get(), "mediaCodecBridge",
+      "()Ldev/cobalt/media/MediaCodecBridge;");
 
   if (!j_media_codec_bridge) {
+    ScopedLocalJavaRef<jstring> j_error_message(
+        env->CallObjectMethodOrAbort(j_create_media_codec_bridge_result.Get(),
+                                     "errorMessage", "()Ljava/lang/String;"));
+    *error_message = env->GetStringStandardUTFOrAbort(j_error_message.Get());
     return scoped_ptr<MediaCodecBridge>(NULL);
   }
 
diff --git a/src/starboard/android/shared/media_codec_bridge.h b/src/starboard/android/shared/media_codec_bridge.h
index 0937860..1fc6618 100644
--- a/src/starboard/android/shared/media_codec_bridge.h
+++ b/src/starboard/android/shared/media_codec_bridge.h
@@ -107,7 +107,8 @@
       jobject j_surface,
       jobject j_media_crypto,
       const SbMediaColorMetadata* color_metadata,
-      bool require_software_codec);
+      bool require_software_codec,
+      std::string* error_message);
 
   ~MediaCodecBridge();
 
diff --git a/src/starboard/android/shared/media_decoder.cc b/src/starboard/android/shared/media_decoder.cc
index b9ade2d..81038c7 100644
--- a/src/starboard/android/shared/media_decoder.cc
+++ b/src/starboard/android/shared/media_decoder.cc
@@ -107,7 +107,8 @@
                            jobject j_output_surface,
                            SbDrmSystem drm_system,
                            const SbMediaColorMetadata* color_metadata,
-                           bool require_software_codec)
+                           bool require_software_codec,
+                           std::string* error_message)
     : media_type_(kSbMediaTypeVideo),
       host_(host),
       drm_system_(static_cast<DrmSystem*>(drm_system)),
@@ -116,9 +117,10 @@
   SB_DCHECK(!drm_system_ || j_media_crypto);
   media_codec_bridge_ = MediaCodecBridge::CreateVideoMediaCodecBridge(
       video_codec, width, height, this, j_output_surface, j_media_crypto,
-      color_metadata, require_software_codec);
+      color_metadata, require_software_codec, error_message);
   if (!media_codec_bridge_) {
-    SB_LOG(ERROR) << "Failed to create video media codec bridge.";
+    SB_LOG(ERROR) << "Failed to create video media codec bridge with error: "
+                  << *error_message;
   }
 }
 
diff --git a/src/starboard/android/shared/media_decoder.h b/src/starboard/android/shared/media_decoder.h
index a474746..41a7a11 100644
--- a/src/starboard/android/shared/media_decoder.h
+++ b/src/starboard/android/shared/media_decoder.h
@@ -78,7 +78,8 @@
                jobject j_output_surface,
                SbDrmSystem drm_system,
                const SbMediaColorMetadata* color_metadata,
-               bool require_software_codec);
+               bool require_software_codec,
+               std::string* error_message);
   ~MediaDecoder();
 
   void Initialize(const ErrorCB& error_cb);
diff --git a/src/starboard/android/shared/media_get_max_buffer_capacity.cc b/src/starboard/android/shared/media_get_max_buffer_capacity.cc
index 1d3899b..591923d 100644
--- a/src/starboard/android/shared/media_get_max_buffer_capacity.cc
+++ b/src/starboard/android/shared/media_get_max_buffer_capacity.cc
@@ -18,10 +18,6 @@
                                 int resolution_width,
                                 int resolution_height,
                                 int bits_per_pixel) {
-  SB_UNREFERENCED_PARAMETER(codec);
-  SB_UNREFERENCED_PARAMETER(resolution_width);
-  SB_UNREFERENCED_PARAMETER(resolution_height);
-  SB_UNREFERENCED_PARAMETER(bits_per_pixel);
   // TODO: refine this to a more reasonable value, taking into account
   // resolution. On most platforms this is 36 * 1024 * 1024 for 1080p, and
   // 65 * 1024 * 1024 for 4k.
diff --git a/src/starboard/android/shared/media_is_audio_supported.cc b/src/starboard/android/shared/media_is_audio_supported.cc
index 9952bf2..c524a9a 100644
--- a/src/starboard/android/shared/media_is_audio_supported.cc
+++ b/src/starboard/android/shared/media_is_audio_supported.cc
@@ -27,8 +27,6 @@
 bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
                              const char* content_type,
                              int64_t bitrate) {
-  SB_UNREFERENCED_PARAMETER(content_type);
-
   // Android now uses libopus based opus decoder.
   if (audio_codec == kSbMediaAudioCodecOpus &&
       bitrate < kSbMediaMaxAudioBitrateInBitsPerSecond) {
diff --git a/src/starboard/android/shared/media_is_video_supported.cc b/src/starboard/android/shared/media_is_video_supported.cc
index fb9900a..a0c42d0 100644
--- a/src/starboard/android/shared/media_is_video_supported.cc
+++ b/src/starboard/android/shared/media_is_video_supported.cc
@@ -86,12 +86,8 @@
       return false;
     }
   }
-  SB_UNREFERENCED_PARAMETER(content_type);
-  SB_UNREFERENCED_PARAMETER(profile);
-  SB_UNREFERENCED_PARAMETER(level);
   // While not necessarily true, for now we assume that all Android devices
   // can play decode-to-texture video just as well as normal video.
-  SB_UNREFERENCED_PARAMETER(decode_to_texture_required);
 
   const char* mime = SupportedVideoCodecToMimeType(video_codec);
   if (!mime) {
diff --git a/src/starboard/android/shared/player_components_factory.cc b/src/starboard/android/shared/player_components_factory.cc
index ebddae0..948b85a 100644
--- a/src/starboard/android/shared/player_components_factory.cc
+++ b/src/starboard/android/shared/player_components_factory.cc
@@ -92,14 +92,15 @@
               creation_parameters.drm_system(),
               creation_parameters.output_mode(),
               creation_parameters.decode_target_graphics_context_provider(),
-              creation_parameters.max_video_capabilities()));
+              creation_parameters.max_video_capabilities(), error_message));
       if (video_decoder_impl->is_valid()) {
         *video_renderer_sink = video_decoder_impl->GetSink();
         video_decoder->reset(video_decoder_impl.release());
       } else {
         video_decoder->reset();
         *video_renderer_sink = NULL;
-        *error_message = "Failed to create video decoder.";
+        *error_message =
+            "Failed to create video decoder with error: " + *error_message;
         return false;
       }
 
diff --git a/src/starboard/android/shared/player_create.cc b/src/starboard/android/shared/player_create.cc
index 2b3e80c..e2cfb48 100644
--- a/src/starboard/android/shared/player_create.cc
+++ b/src/starboard/android/shared/player_create.cc
@@ -41,8 +41,6 @@
                         SbPlayerErrorFunc player_error_func,
                         void* context,
                         SbDecodeTargetGraphicsContextProvider* provider) {
-  SB_UNREFERENCED_PARAMETER(window);
-
   if (!creation_param) {
     SB_LOG(ERROR) << "CreationParam cannot be null.";
     return kSbPlayerInvalid;
diff --git a/src/starboard/android/shared/sdk_utils.py b/src/starboard/android/shared/sdk_utils.py
index dee8241d..b4d6a91 100644
--- a/src/starboard/android/shared/sdk_utils.py
+++ b/src/starboard/android/shared/sdk_utils.py
@@ -1,3 +1,5 @@
+# Lint as: python2
+
 # Copyright 2016 The Cobalt Authors. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,6 +15,7 @@
 # limitations under the License.
 """Utilities to use the toolchain from the Android NDK."""
 
+import errno
 import fcntl
 import logging
 import os
@@ -21,27 +24,26 @@
 import subprocess
 import sys
 import time
-import urllib
 import zipfile
+import requests
 
 from starboard.tools import build
 
 # Which version of the Android NDK and CMake to install and build with.
 # Note that build.gradle parses these out of this file too.
-_NDK_VERSION = '21.0.6113669'
+_NDK_VERSION = '21.1.6352462'
 _CMAKE_VERSION = '3.10.2.4988404'
 
 # Packages to install in the Android SDK.
 # We download ndk-bundle separately, so it's not in this list.
 # Get available packages from "sdkmanager --list --verbose"
 _ANDROID_SDK_PACKAGES = [
-    'build-tools;29.0.2',
+    'build-tools;30.0.0-rc4',  # TODO: Change to the stable released SDK
     'cmake;' + _CMAKE_VERSION,
     'cmdline-tools;1.0',
     'emulator',
     'extras;android;m2repository',
     'extras;google;m2repository',
-    'lldb;3.1',
     'ndk;' + _NDK_VERSION,
     'patcher;v4',
     'platforms;android-29',
@@ -88,7 +90,16 @@
 
 
 def _DownloadAndUnzipFile(url, destination_path):
-  dl_file, dummy_headers = urllib.urlretrieve(url)
+  """Download a zip file from a url and uncompress it."""
+  shutil.rmtree(destination_path, ignore_errors=True)
+  try:
+    os.makedirs(destination_path)
+  except OSError as e:
+    if e.errno != errno.EEXIST:
+      raise
+  dl_file = os.path.join(destination_path, 'tmp.zip')
+  request = requests.get(url, allow_redirects=True)
+  open(dl_file, 'wb').write(request.content)
   _UnzipFile(dl_file, destination_path)
 
 
@@ -125,8 +136,7 @@
         logging.warning(msg)
 
       if not os.path.exists(GetNdkPath()):
-        logging.error('Error: ANDROID_HOME is is missing NDK %s.',
-                      _NDK_VERSION)
+        logging.error('Error: ANDROID_HOME is is missing NDK %s.', _NDK_VERSION)
         sys.exit(1)
 
       reply = raw_input(
@@ -163,8 +173,8 @@
   section_re = re.compile(r'^[A-Z][^:]*:$')
   version_re = re.compile(r'^\s+Version:\s+(\S+)')
 
-  p = subprocess.Popen(
-      [_SDKMANAGER_TOOL, '--list', '--verbose'], stdout=subprocess.PIPE)
+  p = subprocess.Popen([_SDKMANAGER_TOOL, '--list', '--verbose'],
+                       stdout=subprocess.PIPE)
 
   installed_package_versions = {}
   new_style = False
@@ -244,10 +254,19 @@
       [_SDKMANAGER_TOOL, '--verbose'] + _ANDROID_SDK_PACKAGES, stdin=stdin)
 
   if _IsOnBuildbot():
-    time.sleep(_SDK_LICENSE_PROMPT_SLEEP_SECONDS)
     try:
+      # Accept "Terms and Conditions" (android-sdk-license)
+      time.sleep(_SDK_LICENSE_PROMPT_SLEEP_SECONDS)
+      p.stdin.write('y\n')
+      # Accept "SDK Preview" license (android-sdk-preview-license)
+      # TODO: Remove when no longer on prerelease SDK (build-tools;30.0.0-rc4).
+      time.sleep(_SDK_LICENSE_PROMPT_SLEEP_SECONDS)
       p.stdin.write('y\n')
     except IOError:
       logging.warning('There were no SDK licenses to accept.')
 
   p.wait()
+  if p.returncode:
+    raise RuntimeError(
+        '\nFailed to install packages with sdkmanager. Exit status = %d' %
+        p.returncode)
diff --git a/src/starboard/android/shared/speech_synthesis_is_supported.cc b/src/starboard/android/shared/speech_synthesis_is_supported.cc
index 1364fbc..ee7f1be 100644
--- a/src/starboard/android/shared/speech_synthesis_is_supported.cc
+++ b/src/starboard/android/shared/speech_synthesis_is_supported.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/speech_synthesis.h"
 
-#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbSpeechSynthesisIsSupported() {
   return true;
diff --git a/src/starboard/android/shared/starboard_platform.gypi b/src/starboard/android/shared/starboard_platform.gypi
index aa9fe4e..2f94003 100644
--- a/src/starboard/android/shared/starboard_platform.gypi
+++ b/src/starboard/android/shared/starboard_platform.gypi
@@ -155,6 +155,7 @@
         'system_has_capability.cc',
         'system_platform_error.cc',
         'system_request_stop.cc',
+        'system_request_suspend.cc',
         'thread_create.cc',
         'thread_create_priority.cc',
         'thread_get_name.cc',
@@ -342,7 +343,8 @@
         '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc',
         '<(DEPTH)/starboard/shared/signal/suspend_signals.cc',
         '<(DEPTH)/starboard/shared/signal/suspend_signals.h',
-        '<(DEPTH)/starboard/shared/signal/system_request_suspend.cc',
+        '<(DEPTH)/starboard/shared/signal/system_request_conceal.cc',
+        '<(DEPTH)/starboard/shared/signal/system_request_freeze.cc',
         '<(DEPTH)/starboard/shared/starboard/application.cc',
         '<(DEPTH)/starboard/shared/starboard/application.h',
         '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
@@ -358,6 +360,7 @@
         '<(DEPTH)/starboard/shared/starboard/drm/drm_close_session.cc',
         '<(DEPTH)/starboard/shared/starboard/drm/drm_destroy_system.cc',
         '<(DEPTH)/starboard/shared/starboard/drm/drm_generate_session_update_request.cc',
+        '<(DEPTH)/starboard/shared/starboard/drm/drm_get_metrics.cc',
         '<(DEPTH)/starboard/shared/starboard/drm/drm_is_server_certificate_updatable.cc',
         '<(DEPTH)/starboard/shared/starboard/drm/drm_system_internal.h',
         '<(DEPTH)/starboard/shared/starboard/drm/drm_update_server_certificate.cc',
@@ -397,6 +400,7 @@
         '<(DEPTH)/starboard/shared/starboard/microphone/microphone_is_sample_rate_supported.cc',
         '<(DEPTH)/starboard/shared/starboard/microphone/microphone_open.cc',
         '<(DEPTH)/starboard/shared/starboard/microphone/microphone_read.cc',
+        '<(DEPTH)/starboard/shared/starboard/memory.cc',
         '<(DEPTH)/starboard/shared/starboard/new.cc',
         '<(DEPTH)/starboard/shared/starboard/player/decoded_audio_internal.cc',
         '<(DEPTH)/starboard/shared/starboard/player/decoded_audio_internal.h',
@@ -448,7 +452,10 @@
         '<(DEPTH)/starboard/shared/stub/system_get_total_gpu_memory.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_used_gpu_memory.cc',
         '<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_blur.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_focus.cc',
         '<(DEPTH)/starboard/shared/stub/system_request_pause.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_reveal.cc',
         '<(DEPTH)/starboard/shared/stub/system_request_unpause.cc',
         '<(DEPTH)/starboard/shared/stub/system_sign_with_certification_secret_key.cc',
         '<(DEPTH)/starboard/shared/stub/thread_context_get_pointer.cc',
diff --git a/src/starboard/android/shared/system_platform_error.cc b/src/starboard/android/shared/system_platform_error.cc
index 2864800..fe1e560 100644
--- a/src/starboard/android/shared/system_platform_error.cc
+++ b/src/starboard/android/shared/system_platform_error.cc
@@ -69,7 +69,6 @@
                                                       jobject unused_this,
                                                       jint jni_response,
                                                       jlong jni_data) {
-  SB_UNREFERENCED_PARAMETER(unused_this);
   SendResponseCallback* send_response_callback =
       reinterpret_cast<SendResponseCallback*>(jni_data);
   if (send_response_callback) {
diff --git a/src/starboard/android/shared/thread_create.cc b/src/starboard/android/shared/thread_create.cc
index 02bf819..6b3ca2d 100644
--- a/src/starboard/android/shared/thread_create.cc
+++ b/src/starboard/android/shared/thread_create.cc
@@ -30,10 +30,9 @@
 namespace shared {
 namespace pthread {
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION && \
-    !SB_HAS(THREAD_PRIORITY_SUPPORT)
+#if SB_API_VERSION < 12 && !SB_HAS(THREAD_PRIORITY_SUPPORT)
 // Default implementation without thread priority support
-void ThreadSetPriority(SbThreadPriority /* priority */) {}
+void ThreadSetPriority(SbThreadPriority priority) {}
 #endif
 
 void PreThreadRun() {}
diff --git a/src/starboard/android/shared/thread_create_priority.cc b/src/starboard/android/shared/thread_create_priority.cc
index fd47954..ee9979b 100644
--- a/src/starboard/android/shared/thread_create_priority.cc
+++ b/src/starboard/android/shared/thread_create_priority.cc
@@ -23,8 +23,7 @@
 namespace shared {
 namespace pthread {
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(THREAD_PRIORITY_SUPPORT)
+#if SB_API_VERSION >= 12 || SB_HAS(THREAD_PRIORITY_SUPPORT)
 
 void SetNiceValue(int nice) {
   int result = setpriority(PRIO_PROCESS, 0, nice);
@@ -65,7 +64,7 @@
   }
 }
 
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(THREAD_PRIORITY_SUPPORT)
 }  // namespace pthread
 }  // namespace shared
diff --git a/src/starboard/android/shared/video_decoder.cc b/src/starboard/android/shared/video_decoder.cc
index 1a32e22..5a5030e 100644
--- a/src/starboard/android/shared/video_decoder.cc
+++ b/src/starboard/android/shared/video_decoder.cc
@@ -136,11 +136,6 @@
   }
 
   void SetBounds(int z_index, int x, int y, int width, int height) override {
-    SB_UNREFERENCED_PARAMETER(z_index);
-    SB_UNREFERENCED_PARAMETER(x);
-    SB_UNREFERENCED_PARAMETER(y);
-    SB_UNREFERENCED_PARAMETER(width);
-    SB_UNREFERENCED_PARAMETER(height);
   }
 
   DrawFrameStatus DrawFrame(const scoped_refptr<VideoFrame>& frame,
@@ -161,7 +156,8 @@
                            SbPlayerOutputMode output_mode,
                            SbDecodeTargetGraphicsContextProvider*
                                decode_target_graphics_context_provider,
-                           const char* max_video_capabilities)
+                           const char* max_video_capabilities,
+                           std::string* error_message)
     : video_codec_(video_codec),
       drm_system_(static_cast<DrmSystem*>(drm_system)),
       output_mode_(output_mode),
@@ -171,6 +167,8 @@
       surface_condition_variable_(surface_destroy_mutex_),
       require_software_codec_(max_video_capabilities &&
                               SbStringGetLength(max_video_capabilities) > 0) {
+  SB_DCHECK(error_message);
+
   if (require_software_codec_) {
     SB_DCHECK(output_mode_ == kSbPlayerOutputModeDecodeToTexture);
   }
@@ -178,8 +176,10 @@
     number_of_hardware_decoders_++;
   }
 
-  if (!InitializeCodec()) {
-    SB_LOG(ERROR) << "Failed to initialize video decoder.";
+  if (!InitializeCodec(error_message)) {
+    *error_message =
+        "Failed to initialize video decoder with error: " + *error_message;
+    SB_LOG(ERROR) << *error_message;
     TeardownCodec();
   }
 }
@@ -252,14 +252,18 @@
     // Re-initialize the codec now if it was torn down either in |Reset| or
     // because we need to change the color metadata.
     if (media_decoder_ == NULL) {
-      if (!InitializeCodec()) {
-        SB_LOG(ERROR) << "Failed to reinitialize codec.";
+      std::string error_message;
+      if (!InitializeCodec(&error_message)) {
+        error_message =
+            "Failed to reinitialize codec with error: " + error_message;
+        SB_LOG(ERROR) << error_message;
         TeardownCodec();
-        error_cb_(kSbPlayerErrorDecode, "Cannot initialize codec.");
+        ReportError(kSbPlayerErrorDecode, error_message);
         return;
       }
     }
   }
+
   // There's a race condition when suspending the app. If surface view is
   // destroyed before video decoder stopped, |media_decoder_| could be null
   // here. And error_cb_() could be handled asynchronously. It's possible
@@ -306,8 +310,10 @@
   first_buffer_received_ = false;
 }
 
-bool VideoDecoder::InitializeCodec() {
+bool VideoDecoder::InitializeCodec(std::string* error_message) {
   SB_DCHECK(BelongsToCurrentThread());
+  SB_DCHECK(error_message);
+
   // Setup the output surface object.  If we are in punch-out mode, target
   // the passed in Android video surface.  If we are in decode-to-texture
   // mode, create a surface from a new texture target and use that as the
@@ -329,7 +335,8 @@
           DecodeTargetCreate(decode_target_graphics_context_provider_,
                              kSbDecodeTargetFormat1PlaneRGBA, 0, 0);
       if (!SbDecodeTargetIsValid(decode_target)) {
-        SB_LOG(ERROR) << "Could not acquire a decode target from provider.";
+        *error_message = "Could not acquire a decode target from provider.";
+        SB_LOG(ERROR) << *error_message;
         return false;
       }
       j_output_surface = decode_target->data->surface;
@@ -346,14 +353,16 @@
     } break;
   }
   if (!j_output_surface) {
-    SB_LOG(ERROR) << "Video surface does not exist.";
+    *error_message = "Video surface does not exist.";
+    SB_LOG(ERROR) << *error_message;
     return false;
   }
 
   int width, height;
   if (!GetVideoWindowSize(&width, &height)) {
-    SB_LOG(ERROR)
-        << "Can't initialize the codec since we don't have a video window.";
+    *error_message =
+        "Can't initialize the codec since we don't have a video window.";
+    SB_LOG(ERROR) << *error_message;
     return false;
   }
 
@@ -361,10 +370,12 @@
   SB_DCHECK(!drm_system_ || j_media_crypto);
   media_decoder_.reset(new MediaDecoder(
       this, video_codec_, width, height, j_output_surface, drm_system_,
-      color_metadata_ ? &*color_metadata_ : nullptr, require_software_codec_));
+      color_metadata_ ? &*color_metadata_ : nullptr, require_software_codec_,
+      error_message));
   if (media_decoder_->is_valid()) {
     if (error_cb_) {
-      media_decoder_->Initialize(error_cb_);
+      media_decoder_->Initialize(
+          std::bind(&VideoDecoder::ReportError, this, _1, _2));
     }
     return true;
   }
@@ -585,6 +596,17 @@
   surface_condition_variable_.Signal();
 }
 
+void VideoDecoder::ReportError(SbPlayerError error,
+                               const std::string& error_message) {
+  SB_DCHECK(error_cb_);
+
+  if (!error_cb_) {
+    return;
+  }
+
+  error_cb_(kSbPlayerErrorDecode, error_message);
+}
+
 }  // namespace shared
 }  // namespace android
 }  // namespace starboard
diff --git a/src/starboard/android/shared/video_decoder.h b/src/starboard/android/shared/video_decoder.h
index 46b260b..8202f57 100644
--- a/src/starboard/android/shared/video_decoder.h
+++ b/src/starboard/android/shared/video_decoder.h
@@ -60,7 +60,8 @@
                SbPlayerOutputMode output_mode,
                SbDecodeTargetGraphicsContextProvider*
                    decode_target_graphics_context_provider,
-               const char* max_video_capabilities);
+               const char* max_video_capabilities,
+               std::string* error_message);
   ~VideoDecoder() override;
 
   scoped_refptr<VideoRendererSink> GetSink();
@@ -89,7 +90,7 @@
  private:
   // Attempt to initialize the codec.  Returns whether initialization was
   // successful.
-  bool InitializeCodec();
+  bool InitializeCodec(std::string* error_message);
   void TeardownCodec();
 
   void ProcessOutputBuffer(MediaCodecBridge* media_codec_bridge,
@@ -99,6 +100,7 @@
   void OnFlushing() override;
 
   void OnSurfaceDestroyed() override;
+  void ReportError(SbPlayerError error, const std::string& error_message);
 
   static int number_of_hardware_decoders_;
 
diff --git a/src/starboard/android/shared/window_blur_on_screen_keyboard.cc b/src/starboard/android/shared/window_blur_on_screen_keyboard.cc
index 88e6107..dd2048f 100644
--- a/src/starboard/android/shared/window_blur_on_screen_keyboard.cc
+++ b/src/starboard/android/shared/window_blur_on_screen_keyboard.cc
@@ -14,11 +14,10 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 void SbWindowBlurOnScreenKeyboard(SbWindow window, int ticket) {
   // Stub.
   return;
 }
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_focus_on_screen_keyboard.cc b/src/starboard/android/shared/window_focus_on_screen_keyboard.cc
index 31fbde3..8ffdaba 100644
--- a/src/starboard/android/shared/window_focus_on_screen_keyboard.cc
+++ b/src/starboard/android/shared/window_focus_on_screen_keyboard.cc
@@ -14,11 +14,10 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 void SbWindowFocusOnScreenKeyboard(SbWindow window, int ticket) {
   // Stub.
   return;
 }
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_get_on_screen_keyboard_bounding_rect.cc b/src/starboard/android/shared/window_get_on_screen_keyboard_bounding_rect.cc
index 242a2ac..b793f5b 100644
--- a/src/starboard/android/shared/window_get_on_screen_keyboard_bounding_rect.cc
+++ b/src/starboard/android/shared/window_get_on_screen_keyboard_bounding_rect.cc
@@ -14,12 +14,11 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 bool SbWindowGetOnScreenKeyboardBoundingRect(SbWindow window,
                                              SbWindowRect* bounding_rect) {
   // Stub.
   return true;
 }
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_hide_on_screen_keyboard.cc b/src/starboard/android/shared/window_hide_on_screen_keyboard.cc
index 8163e62..7cf008c 100644
--- a/src/starboard/android/shared/window_hide_on_screen_keyboard.cc
+++ b/src/starboard/android/shared/window_hide_on_screen_keyboard.cc
@@ -16,12 +16,11 @@
 
 #include "starboard/android/shared/application_android.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 void SbWindowHideOnScreenKeyboard(SbWindow window, int ticket) {
   starboard::android::shared::ApplicationAndroid::Get()
       ->SbWindowHideOnScreenKeyboard(window, ticket);
   return;
 }
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_is_on_screen_keyboard_shown.cc b/src/starboard/android/shared/window_is_on_screen_keyboard_shown.cc
index 61f80d2..71ac1a0 100644
--- a/src/starboard/android/shared/window_is_on_screen_keyboard_shown.cc
+++ b/src/starboard/android/shared/window_is_on_screen_keyboard_shown.cc
@@ -20,8 +20,7 @@
 using starboard::android::shared::JniEnvExt;
 using starboard::android::shared::ScopedLocalJavaRef;
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 bool SbWindowIsOnScreenKeyboardShown(SbWindow window) {
   JniEnvExt* env = JniEnvExt::Get();
 
@@ -32,5 +31,5 @@
       j_keyboard_editor.Get(), "isKeyboardShowing", "()Z");
   return is_keyboard_shown;
 }
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_on_screen_keyboard_is_supported.cc b/src/starboard/android/shared/window_on_screen_keyboard_is_supported.cc
index b9eb7e8..ab63af8 100644
--- a/src/starboard/android/shared/window_on_screen_keyboard_is_supported.cc
+++ b/src/starboard/android/shared/window_on_screen_keyboard_is_supported.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbWindowOnScreenKeyboardIsSupported() {
   return false;
diff --git a/src/starboard/android/shared/window_on_screen_keyboard_suggestions_supported.cc b/src/starboard/android/shared/window_on_screen_keyboard_suggestions_supported.cc
index b2e51d1..050a2f8 100644
--- a/src/starboard/android/shared/window_on_screen_keyboard_suggestions_supported.cc
+++ b/src/starboard/android/shared/window_on_screen_keyboard_suggestions_supported.cc
@@ -14,10 +14,9 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 bool SbWindowOnScreenKeyboardSuggestionsSupported(SbWindow window) {
   return true;
 }
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_set_on_screen_keyboard_keep_focus.cc b/src/starboard/android/shared/window_set_on_screen_keyboard_keep_focus.cc
index c6c08fd..c940aad 100644
--- a/src/starboard/android/shared/window_set_on_screen_keyboard_keep_focus.cc
+++ b/src/starboard/android/shared/window_set_on_screen_keyboard_keep_focus.cc
@@ -18,8 +18,7 @@
 
 using starboard::android::shared::JniEnvExt;
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 void SbWindowSetOnScreenKeyboardKeepFocus(SbWindow window, bool keep_focus) {
   JniEnvExt* env = JniEnvExt::Get();
   jobject j_keyboard_editor = env->CallStarboardObjectMethodOrAbort(
@@ -28,5 +27,5 @@
                              keep_focus);
   return;
 }
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_show_on_screen_keyboard.cc b/src/starboard/android/shared/window_show_on_screen_keyboard.cc
index aa5afee..a9f73fa 100644
--- a/src/starboard/android/shared/window_show_on_screen_keyboard.cc
+++ b/src/starboard/android/shared/window_show_on_screen_keyboard.cc
@@ -16,8 +16,7 @@
 
 #include "starboard/android/shared/application_android.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 void SbWindowShowOnScreenKeyboard(SbWindow window,
                                   const char* input_text,
                                   int ticket) {
@@ -25,5 +24,5 @@
       ->SbWindowShowOnScreenKeyboard(window, input_text, ticket);
   return;
 }
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_update_on_screen_keyboard_suggestions.cc b/src/starboard/android/shared/window_update_on_screen_keyboard_suggestions.cc
index 86b2c13..217c5ae 100644
--- a/src/starboard/android/shared/window_update_on_screen_keyboard_suggestions.cc
+++ b/src/starboard/android/shared/window_update_on_screen_keyboard_suggestions.cc
@@ -16,8 +16,7 @@
 
 #include "starboard/android/shared/application_android.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 void SbWindowUpdateOnScreenKeyboardSuggestions(SbWindow window,
                                                const char* suggestions[],
                                                int num_suggestions,
@@ -31,5 +30,5 @@
                                                   ticket);
   return;
 }
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/x86/gyp_configuration.py b/src/starboard/android/x86/gyp_configuration.py
index 258382c..80134e6 100644
--- a/src/starboard/android/x86/gyp_configuration.py
+++ b/src/starboard/android/x86/gyp_configuration.py
@@ -18,4 +18,6 @@
 
 def CreatePlatformConfig():
   return shared_configuration.AndroidConfiguration(
-      'android-x86', 'x86', sabi_json_path='starboard/sabi/x86/sabi.json')
+      'android-x86',
+      'x86',
+      sabi_json_path='starboard/sabi/x86/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/audio_sink.h b/src/starboard/audio_sink.h
index 7bb5805..49ab5c4 100644
--- a/src/starboard/audio_sink.h
+++ b/src/starboard/audio_sink.h
@@ -63,21 +63,17 @@
 
 // Callback used to report frames consumed.  The consumed frames will be
 // removed from the source frame buffer to free space for new audio frames.
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+#if SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+typedef void (*SbAudioSinkConsumeFramesFunc)(int frames_consumed,
+                                             void* context);
+#else   // SB_API_VERSION >=  12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 // When |frames_consumed| is updated asynchnously and the last time that it has
 // been updated is known, it can be passed in |frames_consumed_at| so the audio
 // time calculating can be more accurate.
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-typedef void (*SbAudioSinkConsumeFramesFunc)(
-    int frames_consumed,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-    SbTime frames_consumed_at,
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-    void* context);
+typedef void (*SbAudioSinkConsumeFramesFunc)(int frames_consumed,
+                                             SbTime frames_consumed_at,
+                                             void* context);
+#endif  // SB_API_VERSION >=  12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 
 // Well-defined value for an invalid audio sink.
 #define kSbAudioSinkInvalid ((SbAudioSink)NULL)
diff --git a/src/starboard/blitter.h b/src/starboard/blitter.h
index 24ebad9..2d37705 100644
--- a/src/starboard/blitter.h
+++ b/src/starboard/blitter.h
@@ -55,7 +55,7 @@
 #include "starboard/types.h"
 #include "starboard/window.h"
 
-#if SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
+#if SB_API_VERSION < 12 && SB_HAS(BLITTER)
 
 #ifdef __cplusplus
 extern "C" {
@@ -778,6 +778,6 @@
 }  // extern "C"
 #endif
 
-#endif  // SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
+#endif  // SB_API_VERSION < 12 && SB_HAS(BLITTER)
 
 #endif  // STARBOARD_BLITTER_H_
diff --git a/src/starboard/build/base_configuration.gypi b/src/starboard/build/base_configuration.gypi
index 0da4c16..9ba8c66 100644
--- a/src/starboard/build/base_configuration.gypi
+++ b/src/starboard/build/base_configuration.gypi
@@ -218,6 +218,7 @@
             'linker_flags_host%': [
               '-target', 'i386-unknown-linux-gnu',
               '-pthread',
+              '-latomic',
             ],
           }, {
             'compiler_flags_cc_host%': [
diff --git a/src/starboard/build/collect_deploy_content.gypi b/src/starboard/build/collect_deploy_content.gypi
index 86848ba..0ab0db8 100644
--- a/src/starboard/build/collect_deploy_content.gypi
+++ b/src/starboard/build/collect_deploy_content.gypi
@@ -37,6 +37,11 @@
     # should set |content_deploy_use_absolute_symlinks| to 1.
     'content_deploy_use_absolute_symlinks%': 0,
 
+    # Some platforms can only support a limited depth of directory
+    # structure, and this allows the depth of deploy content to be
+    # checked not to exceed that.
+    'content_deploy_max_depth%': 0,
+
     # Implementation detail to add conditional args.
     'collect_deploy_content_extra_args': [],
   },
@@ -66,6 +71,7 @@
       '-i', '<(input_dir)',
       '-o', '<(output_dir)',
       '-s', '<(content_deploy_stamp_file)',
+      '--max_depth', '<(content_deploy_max_depth)',
       '<@(collect_deploy_content_extra_args)',
       '>@(content_deploy_subdirs)',
     ],
diff --git a/src/starboard/build/collect_deploy_content.py b/src/starboard/build/collect_deploy_content.py
old mode 100644
new mode 100755
index 8d3fffd..35176bb
--- a/src/starboard/build/collect_deploy_content.py
+++ b/src/starboard/build/collect_deploy_content.py
@@ -39,6 +39,26 @@
   port_symlink.Rmtree(path)
 
 
+def _CheckDepth(max_depth, content_dir):
+  """Check that the number of content path components doesn't exceed max_depth.
+
+  The depth is counted as each path component from the content directory itself
+  to the deepest file, inclusive.
+  """
+  # Tuple (depth, path) of a file that's deepest in content_dir.
+  walk_deepest = max(
+      (root.count(os.sep) + 1, os.path.join(root, (files + dirs)[0]))
+      for root, dirs, files in os.walk(content_dir, followlinks=True))
+  # Relative path of the deepest file, including the content directory itself.
+  deepest_file = os.path.relpath(walk_deepest[1],
+                                 os.path.join(content_dir, os.pardir))
+  depth = deepest_file.count(os.sep) + 1  # +1 for fencepost error
+  logging.info('depth %d: %s', depth, deepest_file)
+  if depth > max_depth:
+    raise RuntimeError('Content is %d levels deep (max allowed is %d): %s' %
+                       (depth, max_depth, deepest_file))
+
+
 def main(argv):
   parser = argparse.ArgumentParser()
   parser.add_argument(
@@ -51,6 +71,12 @@
       required=True,
       help='stamp file to update after the output directory is populated')
   parser.add_argument(
+      '--max_depth',
+      type=int,
+      help='maximum depth of directories allowed. Depth is not checked if '
+      'unspecified or 0. E.g. if output_dir is "content/" then '
+      '"content/web/foo/file.txt" is depth of 4.')
+  parser.add_argument(
       '--use_absolute_symlinks',
       action='store_true',
       help='Generated symlinks are stored as absolute paths.')
@@ -67,6 +93,7 @@
     log_level = logging.WARNING
   logging.basicConfig(level=log_level, format='COLLECT CONTENT: %(message)s')
 
+  logging.info('max_depth: %s', options.max_depth)
   logging.info('< %s', options.input_dir)
   logging.info('> %s', options.output_dir)
   for subdir in options.subdirs:
@@ -114,6 +141,9 @@
     else:
       port_symlink.MakeSymLink(target_path=rel_path, link_path=dst_path)
 
+  if options.max_depth:
+    _CheckDepth(options.max_depth, options.output_dir)
+
   if options.stamp_file:
     with open(options.stamp_file, 'w') as stamp_file:
       stamp_file.write('\n'.join(options.subdirs))
diff --git a/src/starboard/build/platform_configuration.py b/src/starboard/build/platform_configuration.py
index 2d53f61..b41e4e6 100644
--- a/src/starboard/build/platform_configuration.py
+++ b/src/starboard/build/platform_configuration.py
@@ -21,6 +21,7 @@
 import _env  # pylint: disable=unused-import, relative-import
 from starboard.build.application_configuration import ApplicationConfiguration
 from starboard.optional import get_optional_tests
+from starboard.sabi import sabi
 from starboard.tools import environment
 from starboard.tools import paths
 from starboard.tools import platform
@@ -256,7 +257,14 @@
         # V8 are supported.  Note that V8 can only be used on platforms that
         # support JIT.
         'javascript_engine': 'v8',
-        'sabi_json_path': self.GetPathToSabiJsonFile(),
+
+        # If the path to the Starboard ABI file is able to be formatted, it will
+        # be using the experimental Starboard API version of the file, i.e.
+        # |sabi.SB_API_VERSION|. Otherwise, the value provided is just assumed
+        # to be a complete path to a Starboard ABI file.
+        'sabi_json_path':
+            self.GetPathToSabiJsonFile().format(
+                sb_api_version=sabi.SB_API_VERSION),
 
         # TODO: Remove these compatibility variables.
         'cobalt_config': config_name,
@@ -282,14 +290,14 @@
     """Returns the instance of the toolchain implementation class."""
     return None
 
-  def GetTargetToolchain(self):
+  def GetTargetToolchain(self, **kwargs):
     """Returns a list of target tools."""
     # TODO: If this method throws |NotImplementedError|, GYP will fall back to
     #       the legacy toolchain. Once all platforms are migrated to the
     #       abstract toolchain, this method should be made |@abstractmethod|.
     raise NotImplementedError()
 
-  def GetHostToolchain(self):
+  def GetHostToolchain(self, **kwargs):
     """Returns a list of host tools."""
     # TODO: If this method throws |NotImplementedError|, GYP will fall back to
     #       the legacy toolchain. Once all platforms are migrated to the
@@ -338,8 +346,14 @@
   def GetPathToSabiJsonFile(self):
     """Gets the path to the JSON file with Starboard ABI information for the build.
 
+    Examples:
+        'starboard/sabi/arm64/sabi-v12.json'
+        'starboard/sabi/arm64/sabi-v{sb_api_version}.json'
+
     Returns:
-      A string path to the appropriate Starboard ABI JSON file. This file is
+      A string path to the appropriate Starboard ABI JSON file. This path can
+      either be a complete path, or be capable of being formatted with an
+      integer representing the desired Starboard API version. This file is
       required for a variety of definitions and variables pertaining to the ABI.
     """
     return 'starboard/sabi/default/sabi.json'
diff --git a/src/starboard/client_porting/eztime/eztime.h b/src/starboard/client_porting/eztime/eztime.h
index 3e8138c..4ed200a 100644
--- a/src/starboard/client_porting/eztime/eztime.h
+++ b/src/starboard/client_porting/eztime/eztime.h
@@ -15,6 +15,8 @@
 #ifndef STARBOARD_CLIENT_PORTING_EZTIME_EZTIME_H_
 #define STARBOARD_CLIENT_PORTING_EZTIME_EZTIME_H_
 
+#if defined(STARBOARD)
+
 #include "starboard/common/log.h"
 #include "starboard/time.h"
 #include "starboard/types.h"
@@ -207,4 +209,6 @@
 }  // extern "C"
 #endif
 
+#endif  // STARBOARD
+
 #endif  // STARBOARD_CLIENT_PORTING_EZTIME_EZTIME_H_
diff --git a/src/starboard/client_porting/eztime/test_constants.h b/src/starboard/client_porting/eztime/test_constants.h
index f95ba7f..92e0e59 100644
--- a/src/starboard/client_porting/eztime/test_constants.h
+++ b/src/starboard/client_porting/eztime/test_constants.h
@@ -15,6 +15,8 @@
 #ifndef STARBOARD_CLIENT_PORTING_EZTIME_TEST_CONSTANTS_H_
 #define STARBOARD_CLIENT_PORTING_EZTIME_TEST_CONSTANTS_H_
 
+#if defined(STARBOARD)
+
 #include "starboard/client_porting/eztime/eztime.h"
 
 namespace starboard {
@@ -64,4 +66,6 @@
 }  // namespace client_porting
 }  // namespace starboard
 
+#endif  // STARBOARD
+
 #endif  // STARBOARD_CLIENT_PORTING_EZTIME_TEST_CONSTANTS_H_
diff --git a/src/starboard/client_porting/icu_init/icu_init.cc b/src/starboard/client_porting/icu_init/icu_init.cc
index 461532e..838fe3a 100644
--- a/src/starboard/client_porting/icu_init/icu_init.cc
+++ b/src/starboard/client_porting/icu_init/icu_init.cc
@@ -25,6 +25,7 @@
 #include "starboard/common/log.h"
 #include "starboard/configuration.h"
 #include "starboard/configuration_constants.h"
+#include "starboard/file.h"
 #include "starboard/once.h"
 #include "starboard/system.h"
 
@@ -41,9 +42,27 @@
   bool result = SbSystemGetPath(kSbSystemPathContentDirectory, base_path.data(),
                                 base_path.size());
   SB_DCHECK(result);
+
   std::string data_path(base_path.data());
   data_path += kSbFileSepString;
   data_path += "icu";
+
+#if SB_IS(EVERGREEN)
+  // If the icu tables are not under the content directory, use the
+  // storage directory. This minimizes Evergreen's storage usage
+  // on the device, as it can share the tables under
+  // storage between all the installations, but still has the option
+  // to use its own tables under content.
+  if (!SbFileExists(data_path.c_str())) {
+    bool result = SbSystemGetPath(kSbSystemPathStorageDirectory,
+                                  base_path.data(), base_path.size());
+    SB_DCHECK(result);
+    data_path = base_path.data();
+    data_path += kSbFileSepString;
+    data_path += "icu";
+    SbLogFormatF("Using icu tables from: %s\n", data_path.c_str());
+  }
+#endif
   data_path += kSbFileSepString;
 #if U_IS_BIG_ENDIAN
   data_path += "icudt56b";
diff --git a/src/starboard/client_porting/icu_init/icu_init.h b/src/starboard/client_porting/icu_init/icu_init.h
index 5c8332f..73a451b 100644
--- a/src/starboard/client_porting/icu_init/icu_init.h
+++ b/src/starboard/client_porting/icu_init/icu_init.h
@@ -15,6 +15,8 @@
 #ifndef STARBOARD_CLIENT_PORTING_ICU_INIT_ICU_INIT_H_
 #define STARBOARD_CLIENT_PORTING_ICU_INIT_ICU_INIT_H_
 
+#if defined(STARBOARD)
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -29,4 +31,6 @@
 }  // extern "C"
 #endif
 
+#endif  // STARBOARD
+
 #endif  // STARBOARD_CLIENT_PORTING_ICU_INIT_ICU_INIT_H_
diff --git a/src/starboard/client_porting/poem/getenv_stub_poem.h b/src/starboard/client_porting/poem/getenv_stub_poem.h
index e6cb362..fec8072 100644
--- a/src/starboard/client_porting/poem/getenv_stub_poem.h
+++ b/src/starboard/client_porting/poem/getenv_stub_poem.h
@@ -17,6 +17,8 @@
 #ifndef STARBOARD_CLIENT_PORTING_POEM_GETENV_STUB_POEM_H_
 #define STARBOARD_CLIENT_PORTING_POEM_GETENV_STUB_POEM_H_
 
+#if defined(STARBOARD)
+
 #include <stdlib.h>
 
 #include "starboard/configuration.h"
@@ -25,4 +27,6 @@
   return NULL;
 }
 
+#endif  // STARBOARD
+
 #endif  // STARBOARD_CLIENT_PORTING_POEM_GETENV_STUB_POEM_H_
diff --git a/src/starboard/client_porting/poem/inet_poem.h b/src/starboard/client_porting/poem/inet_poem.h
index 735f54f..97c48b0 100644
--- a/src/starboard/client_porting/poem/inet_poem.h
+++ b/src/starboard/client_porting/poem/inet_poem.h
@@ -17,6 +17,7 @@
 #ifndef STARBOARD_CLIENT_PORTING_POEM_INET_POEM_H_
 #define STARBOARD_CLIENT_PORTING_POEM_INET_POEM_H_
 
+#if defined(STARBOARD)
 #include "starboard/byte_swap.h"
 
 #undef htonl
@@ -31,4 +32,6 @@
 #undef ntohs
 #define ntohs(x) SB_NET_TO_HOST_U16(x)
 
+#endif  // STARBOARD
+
 #endif  // STARBOARD_CLIENT_PORTING_POEM_INET_POEM_H_
diff --git a/src/starboard/client_porting/poem/stdio_leaks_poem.h b/src/starboard/client_porting/poem/stdio_leaks_poem.h
index 166b69b..2c84b25 100644
--- a/src/starboard/client_porting/poem/stdio_leaks_poem.h
+++ b/src/starboard/client_porting/poem/stdio_leaks_poem.h
@@ -30,6 +30,8 @@
 #ifndef STARBOARD_CLIENT_PORTING_POEM_STDIO_LEAKS_POEM_H_
 #define STARBOARD_CLIENT_PORTING_POEM_STDIO_LEAKS_POEM_H_
 
+#if defined(STARBOARD)
+
 #include <cstdio>
 
 #include "starboard/common/string.h"
@@ -50,4 +52,6 @@
 #undef vsnprintf
 #define vsnprintf SbStringFormat
 
+#endif  // STARBOARD
+
 #endif  // STARBOARD_CLIENT_PORTING_POEM_STDIO_LEAKS_POEM_H_
diff --git a/src/starboard/client_porting/poem/string_leaks_poem.h b/src/starboard/client_porting/poem/string_leaks_poem.h
index b6fc0b1..3b392bf 100644
--- a/src/starboard/client_porting/poem/string_leaks_poem.h
+++ b/src/starboard/client_porting/poem/string_leaks_poem.h
@@ -29,6 +29,8 @@
 // guarantee when <cstring> will be included. The order of this include must be
 // preserved or the leaks will not be plugged.
 
+#if defined(STARBOARD)
+
 #include <cstring>
 
 #include "starboard/common/string.h"
@@ -50,4 +52,6 @@
 #undef strlen
 #define strlen std::SbStringGetLength
 
+#endif  // STARBOARD
+
 #endif  // STARBOARD_CLIENT_PORTING_POEM_STRING_LEAKS_POEM_H_
diff --git a/src/starboard/client_porting/poem/strnlen_poem.h b/src/starboard/client_porting/poem/strnlen_poem.h
index c08382f..f714990 100644
--- a/src/starboard/client_porting/poem/strnlen_poem.h
+++ b/src/starboard/client_porting/poem/strnlen_poem.h
@@ -18,6 +18,8 @@
 #ifndef STARBOARD_CLIENT_PORTING_POEM_STRNLEN_POEM_H_
 #define STARBOARD_CLIENT_PORTING_POEM_STRNLEN_POEM_H_
 
+#if defined(STARBOARD)
+
 #include "starboard/configuration.h"
 
 static SB_C_INLINE size_t StringGetLengthFixed(const char* s, size_t maxlen) {
@@ -31,4 +33,6 @@
 #undef strnlen
 #define strnlen(s, maxlen) StringGetLengthFixed(s, maxlen)
 
+#endif  // STARBOARD
+
 #endif  // STARBOARD_CLIENT_PORTING_POEM_STRNLEN_POEM_H_
diff --git a/src/starboard/client_porting/pr_starboard/pr_starboard.h b/src/starboard/client_porting/pr_starboard/pr_starboard.h
index cd41b9e..f4a533b 100644
--- a/src/starboard/client_porting/pr_starboard/pr_starboard.h
+++ b/src/starboard/client_porting/pr_starboard/pr_starboard.h
@@ -20,6 +20,8 @@
 #ifndef STARBOARD_CLIENT_PORTING_PR_STARBOARD_PR_STARBOARD_H_
 #define STARBOARD_CLIENT_PORTING_PR_STARBOARD_PR_STARBOARD_H_
 
+#if defined(STARBOARD)
+
 #include "starboard/common/condition_variable.h"
 #include "starboard/common/log.h"
 #include "starboard/common/mutex.h"
@@ -186,4 +188,6 @@
   return 1000;
 }
 
+#endif  // STARBOAR
+
 #endif  // STARBOARD_CLIENT_PORTING_PR_STARBOARD_PR_STARBOARD_H_
diff --git a/src/starboard/common/common.gyp b/src/starboard/common/common.gyp
index 3b3c0b8..1784d73 100644
--- a/src/starboard/common/common.gyp
+++ b/src/starboard/common/common.gyp
@@ -34,7 +34,6 @@
         'locked_ptr.h',
         'log.cc',
         'log.h',
-        'memory.cc',
         'move.h',
         'murmurhash2.cc',
         'murmurhash2.h',
@@ -71,11 +70,6 @@
         'experimental/concurrency_debug.cc',
         'experimental/concurrency_debug.h',
       ],
-      'defines': [
-        # This must be defined when building Starboard, and must not when
-        # building Starboard client code.
-        'STARBOARD_IMPLEMENTATION',
-      ],
       'conditions': [
         ['custom_media_session_client==0', {
           'sources': [
diff --git a/src/starboard/common/configuration_defaults.cc b/src/starboard/common/configuration_defaults.cc
index 6dbeb7b..3cc0e1d 100644
--- a/src/starboard/common/configuration_defaults.cc
+++ b/src/starboard/common/configuration_defaults.cc
@@ -102,7 +102,7 @@
 }
 
 bool CobaltEnableJitDefault() {
-  return true;
+  return false;
 }
 
 }  // namespace common
diff --git a/src/starboard/common/log.cc b/src/starboard/common/log.cc
index 4fce430..b7a6ab0 100644
--- a/src/starboard/common/log.cc
+++ b/src/starboard/common/log.cc
@@ -45,7 +45,7 @@
 #pragma optimize("", off)
 #endif
 
-void Alias(const void* /*var*/) {}
+void Alias(const void* var) {}
 
 #if defined(COMPILER_MSVC)
 #pragma optimize("", on)
diff --git a/src/starboard/common/optional.h b/src/starboard/common/optional.h
index 9b5d278..23a9616 100644
--- a/src/starboard/common/optional.h
+++ b/src/starboard/common/optional.h
@@ -357,7 +357,7 @@
 }
 
 template <typename T>
-inline bool operator<(const optional<T>& /* lhs */, nullopt_t) {
+inline bool operator<(const optional<T>& lhs, nullopt_t) {
   return false;
 }
 
diff --git a/src/starboard/condition_variable.h b/src/starboard/condition_variable.h
index 09325e0..65df346 100644
--- a/src/starboard/condition_variable.h
+++ b/src/starboard/condition_variable.h
@@ -29,7 +29,7 @@
 extern "C" {
 #endif
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
 
 // Max size of the SbConditionVariable type.
 #define SB_CONDITION_VARIABLE_MAX_SIZE 80
@@ -54,7 +54,7 @@
   { 0 }
 #endif
 
-#endif  // SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#endif  // SB_API_VERSION >= 12
 
 // Enumeration of possible results from waiting on a condvar.
 typedef enum SbConditionVariableResult {
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h
index d130c45..8035099 100644
--- a/src/starboard/configuration.h
+++ b/src/starboard/configuration.h
@@ -42,19 +42,19 @@
 
 // The maximum API version allowed by this version of the Starboard headers,
 // inclusive.
-#define SB_MAXIMUM_API_VERSION 12
+#define SB_MAXIMUM_API_VERSION 13
 
 // The API version that is currently open for changes, and therefore is not
 // stable or frozen. Production-oriented ports should avoid declaring that they
 // implement the experimental Starboard API version.
-#define SB_EXPERIMENTAL_API_VERSION 12
+#define SB_EXPERIMENTAL_API_VERSION 13
 
 // The next API version to be frozen, but is still subject to emergency
 // changes. It is reasonable to base a port on the Release Candidate API
 // version, but be aware that small incompatible changes may still be made to
 // it.
 // The following will be uncommented when an API version is a release candidate.
-#define SB_RELEASE_CANDIDATE_API_VERSION 11
+#define SB_RELEASE_CANDIDATE_API_VERSION 12
 
 // --- Experimental Feature Defines ------------------------------------------
 
@@ -68,225 +68,8 @@
 //   //   exposes functionality for my new feature.
 //   #define SB_MY_EXPERIMENTAL_FEATURE_VERSION SB_EXPERIMENTAL_API_VERSION
 
-// Add support for platform-based UI navigation.
-// The system can be disabled by implementing the function
-// `SbUiNavGetInterface()` to return `false`.  Platform-based UI navigation
-// allows the platform to receive feedback on where UI elements are located and
-// also lets the platform control what is selected and what the scroll
-// parameters are.
-#define SB_UI_NAVIGATION_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Require the OpenGL, Blitter, and Skia renderers on all platforms.
-// The system must implement `SbGetGlesInterface()` in `starboard/gles.h`
-// or use the provided stub implementation, and must do the same for
-// the blitter functions in `starboad/blitter.h`. The provided blitter stubs
-// will return responses that denote failures. The system should implement
-// `SbGetGlesInterface()` to return `nullptr` when OpenGL is not supported and
-// implement `SbBlitterIsBlitterSupported()` to return false when blitter is
-// not supported, as the stubs do.
-//
-// This change also effectively deprecates the gyp variable
-// "enable_map_to_mesh" in favor of CobaltGraphicsExtensionApi function
-// `IsMapToMeshEnabled()` and the command line switch --disable_map_to_mesh.
-// Now, Cobalt will assume the platform supports map_to_mesh, so platforms that
-// do not will have to have return |false| from `IsMapToMeshEnabled()` or use
-// the provided command line switch.
-#define SB_ALL_RENDERERS_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Blitter API is no longer supported on any platform. Use the OpenGL ES
-// interface instead.
-#define SB_BLITTER_DEPRECATED_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Crypto API is no longer supported on any platform. BoringSSL CPU
-// optimizations are used instead.
-#define SB_CRYPTOAPI_DEPRECATED_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Require the captions API.
-// The system must implement the captions functions in
-// `starboard/accessibility.h` or use the provided stub implementations.
-// System caption can be disabled by implementing the function
-// `SbAccessibilityGetCaptionSettings(SbAccessibilityCaptionSettings*
-// caption_settings)` to return false as the stub implementation does.
-// This change also deprecates the SB_HAS_CAPTIONS flag.
-#define SB_CAPTIONS_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Require compilation with Ipv6.
-// Cobalt must be able to determine at runtime if the system supportes Ipv6.
-// Ipv6 can be disabled by defining SB_HAS_IPV6 to 0.
-#define SB_IPV6_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Require the microphone API.
-// The system must implement the microphone functions in
-// `starboard/microphone.h` or use the provided stub functions.
-// The microphone can be disabled by having `SbMicrophoneCreate()` return
-// |kSbMicrophoneInvalid|.
-// This change also deprecates the SB_HAS_MICROPHONE flag.
-#define SB_MICROPHONE_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Require the memory mapping API.
-// The system must implement the memory mapping functions in
-// `starboard/memory.h` and `starboard/shared/dlmalloc.h` or use the provided
-// stub implementations.
-// This change also deprecates the SB_HAS_MMAP flag.
-#define SB_MMAP_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Require the on screen keyboard API.
-// The system must implement the on screen keyboard functions in
-// `starboard/window.h` or use the provided stub implementations.
-// The on screen keyboard can be disabled by implementing the function
-// `SbWindowOnScreenKeyboardIsSupported()` to return false
-// as the stub implementation does.
-#define SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Require speech recognizer API.
-// The system must implement the functions in `starboard/speech_recognizer.h`
-// or use the provided stub implementations.
-// The speech recognizer can be disabled by implementing the function
-// `SbSpeechRecognizerIsSupported()` to return `false` as the stub
-// implementation does.
-#define SB_SPEECH_RECOGNIZER_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Require the speech synthesis API.
-// The system must implement the speech synthesis function in
-// `starboard/speech_synthesis.h` or use the provided stub implementations.
-// Speech synthesis can be disabled by implementing the function
-// `SbSpeechSynthesisIsSupported()` to return false as the stub
-// implementation does.
-#define SB_SPEECH_SYNTHESIS_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Require the time thread now API.
-// The system must implement the time thread now functions in
-// `starboard/time.h` or use the provided stub implementations.
-// Time thread now can be disabled by implementing the function
-// `SbTimeIsTimeThreadNowSupported()` to return false as the stub
-// implementation does.
-#define SB_TIME_THREAD_NOW_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Introduce the Starboard function SbFileAtomicReplace() to provide the ability
-// to atomically replace the content of a file.
-#define SB_FILE_ATOMIC_REPLACE_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Introduces new system property kSbSystemPathStorageDirectory.
-// Path to directory for permanent storage. Both read and write
-// access are required.
-#define SB_STORAGE_PATH_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Deprecate the usage of SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER.
-#define SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER_DEPRECATED_VERSION \
-  SB_EXPERIMENTAL_API_VERSION
-
-// The variable 'cobalt_minimum_frame_time_in_milliseconds' is deprecated
-// in favor of the usage of
-// 'CobaltExtensionGraphicsApi::GetMinimumFrameIntervalInMilliseconds' API.
-// The declaration of 'GetMinimumFrameIntervalInMilliseconds' can be found
-// in cobalt/renderer/backend/graphics_context.h
-#define SB_COBALT_MINIMUM_FRAME_TIME_DEPRECATED_VERSION \
-  SB_EXPERIMENTAL_API_VERSION
-
-// Introduce Starboard Application Binary Interface (SABI) files.
-//   SABI files are used to describe the configuration for targets such that two
-//   targets, built with the same SABI file and varying toolchains, have
-//   compatible Starboard APIs and ABIs.
-//
-//   With this define, we have:
-//     1) Moved architecture specific defines and configurations from
-//        configuration_public.h and *.gyp[i] files into SABI files.
-//     2) Included the appropriate SABI file in each platform configuration.
-//     3) Included the //starboard/sabi/sabi.gypi file in each platform
-//        configuration which consumes SABI file fields and defines a set of
-//        constants that are accessible when building.
-//     4) Provided a set of tests that ensure the toolchain being used produces
-//        an executable or shared library that conforms to the included SABI
-//        file.
-//
-//  For further information on what is provided by SABI files, or how these
-//  values are consumed, take a look at //starboard/sabi.
-#define SB_SABI_FILE_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Updates the API guarantees of SbMutexAcquireTry.
-// SbMutexAcquireTry now has undefined behavior when it is invoked on a mutex
-// that has already been locked by the calling thread. In addition, since
-// SbMutexAcquireTry was used in SbMutexDestroy, SbMutexDestroy now has
-// undefined behavior when invoked on a locked mutex.
-#define SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Migrate the Starboard configuration variables from macros to extern consts.
-//
-// The migration allows Cobalt to make platform level decisions at runtime
-// instead of compile time which lets us create a more comprehensive Cobalt
-// binary.
-//
-// This means Cobalt must remove all references to these macros that would not
-// translate well to constants, i.e. in compile time references or initializing
-// arrays. Therefore, we needed to change the functionality of the function
-// `SbDirectoryGetNext` in "starboard/directory.h". Because we do not want to
-// use variable length arrays, we pass in a c-string and length to the function
-// to achieve the same result as before when passing in a `SbDirectoryEntry`.
-//
-// A platform will define the extern constants declared in
-// "starboard/configuration_constants.h". The definitions are done in
-// "starboard/<PLATFORM_PATH>/configuration_constants.cc".
-//
-// The exact mapping between macros and extern variables can be found in
-// "starboard/shared/starboard/configuration_constants_compatibility_defines.h"
-// though the naming scheme is very nearly the same: the old SB_FOO macro will
-// always become the constant kSbFoo.
-#define SB_FEATURE_RUNTIME_CONFIGS_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Improve player creation and output mode query.
-// 1. Introduce the new type SbPlayerCreationParam that holds the common
-//    parameters used to create an SbPlayer() and to query for the output mode
-//    support.
-// 2. Replace SbPlayerOutputModeSupported() by SbPlayerGetPreferredOutputMode()
-//    so the SbPlayer implementation can explicitly indicate its preference on
-//    output mode, when all output modes are supported.
-//    For example, Cobalt used to always query for |kSbPlayerOutputModePunchOut|
-//    first, without providing details about the video going to be played, and
-//    not query for output modes if punch out is supported.  The new interface
-//    allows the implementation to fine tune its output mode.  For example, it
-//    may decide to use |kSbPlayerOutputModeDecodeToTexture| for low resolution
-//    videos.
-#define SB_PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT_VERSION \
-  SB_EXPERIMENTAL_API_VERSION
-
-// Introduce error handling into reference SbAudioSinkPrivate implementation in
-// "starboard/shared/starboard/audio_sink/audio_sink_internal.*".
-#define SB_AUDIO_SINK_ERROR_HANDLING_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Defines new, portable thread types with stable ABI for
-// SbThread, SbMutex, SbOnce and SbConditionVariable.
-#define SB_PORTABLE_THREAD_TYPES_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Introduce support of cbcs encryption scheme into SbDrmSystem, as defined in
-// ISO/IEC 23001 part 7.
-#define SB_DRM_CBCS_SUPPORT_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Deprecate the SB_HAS_VIRTUAL_REGIONS flag as all platforms define it to 0.
-#define SB_VIRTUAL_REGIONS_FLAG_DEPRECATED SB_EXPERIMENTAL_API_VERSION
-
-// Add link register to SbThreadContext.
-#define SB_THREAD_CONTEXT_LINK_REGISTER_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Make GYP configuration variables cobalt extensions instead.
-// This change moves all of the GYP configuration variables to be members of
-// the struct declared in "cobalt/extension/configuration.h". All members are
-// function pointers that can be set for each platform, otherwise defaults
-// will be used. These can be referenced through functions declared in
-// "cobalt/configuration/configuration.h", which will use the extension API if
-// available, but will otherwise fall back onto default values.
-#define SB_FEATURE_GYP_CONFIGURATION_VERSION SB_EXPERIMENTAL_API_VERSION
-
-// Add the PCLMULQDQ instruction feature to the Starboard CPU features interface
-// for x86 architectures.
-#define SB_CPU_FEATURE_PCLMULQDQ SB_EXPERIMENTAL_API_VERSION
-
-// |content_type| is added to SbMediaIsVideoSupported() and
-// SbMediaIsAudioSupported().
-#define SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION \
-  SB_EXPERIMENTAL_API_VERSION
-
-// Deprecate support for gles3 features.
-#define SB_GLES3_DEPRECATED_VERSION SB_EXPERIMENTAL_API_VERSION
+// Add Concealed state support.
+#define SB_ADD_CONCEALED_STATE_SUPPORT_VERSION 14
 
 // --- Release Candidate Feature Defines -------------------------------------
 
@@ -378,13 +161,13 @@
 // and all configurations.
 #include STARBOARD_CONFIGURATION_INCLUDE
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
-// After SB_FEATURE_RUNTIME_CONFIGS_VERSION, we start to use runtime constants
+#if SB_API_VERSION < 12
+// After version 12, we start to use runtime constants
 // instead of macros for certain platform dependent configurations. This file
 // substitutes configuration macros for the corresponding runtime constants so
 // we don't reference these constants when they aren't defined.
 #include "starboard/shared/starboard/configuration_constants_compatibility_defines.h"
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
 // --- Overridable Helper Macros ---------------------------------------------
 
@@ -580,14 +363,14 @@
 #error "Your platform must be exactly one of { 32-bit, 64-bit }."
 #endif
 
-#if SB_API_VERSION >= SB_SABI_FILE_VERSION
+#if SB_API_VERSION >= 12
 
 #if !SB_IS(BIG_ENDIAN) && !SB_IS(LITTLE_ENDIAN) || \
     (SB_IS(BIG_ENDIAN) == SB_IS(LITTLE_ENDIAN))
 #error "Your platform's endianness must be defined as big or little."
 #endif
 
-#else   // SB_API_VERSION < SB_SABI_FILE_VERSION
+#else  // SB_API_VERSION < 12
 
 #if SB_IS(ARCH_X86) && SB_IS(64_BIT)
 #undef SB_IS_ARCH_X86
@@ -622,7 +405,7 @@
 #error "SB_IS_LITTLE_ENDIAN is set based on SB_IS_BIG_ENDIAN."
 #endif
 
-#endif  // SB_API_VERSION >= SB_SABI_FILE_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #if (SB_SIZE_OF(POINTER) != 4) && (SB_SIZE_OF(POINTER) != 8)
 #error "Your platform's pointer sizes must be either 32 bit or 64 bit."
@@ -694,7 +477,7 @@
 
 #endif  // SB_API_VERSION >= 11
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
 
 #if defined(SB_DEFAULT_MMAP_THRESHOLD)
 #error \
@@ -759,13 +542,6 @@
 "starboard/<PLATFORM_PATH>/configuration_constants.cc."
 #endif
 
-#if defined(SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING)
-#error \
-    "SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING should not be defined in Starboard " \
-"versions 12 and later. Instead, define kSbHasAsyncAudioFramesReporting in " \
-"starboard/<PLATFORM_PATH>/configuration_constants.cc."
-#endif
-
 #if defined(SB_HAS_MEDIA_WEBM_VP9_SUPPORT)
 #error \
     "SB_HAS_MEDIA_WEBM_VP9_SUPPORT should not be defined in Starboard " \
@@ -895,7 +671,7 @@
 "starboard/<PLATFORM_PATH>/configuration_constants.cc."
 #endif
 
-#else  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else  // SB_API_VERSION >= 12
 
 #if !defined(SB_FILE_MAX_NAME) || SB_FILE_MAX_NAME < 2
 #error "Your platform must define SB_FILE_MAX_NAME > 1."
@@ -915,11 +691,11 @@
 #endif  // defined(SB_HAS_AC3_AUDIO)
 #endif  // SB_API_VERSION >= 11
 
-#if !defined(SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING)
-#error \
-    "Your platform must define SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING in API "\
-    "version 10 or later."
-#endif  // !defined(SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING)
+#if SB_API_VERSION >= 12
+#if defined(SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING)
+#error "SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING has been deprecated."
+#endif  // defined(SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING)
+#endif
 
 #if !defined(SB_HAS_THREAD_PRIORITY_SUPPORT)
 #error "Your platform must define SB_HAS_THREAD_PRIORITY_SUPPORT."
@@ -975,15 +751,14 @@
 #error "SB_PREFERRED_RGBA_BYTE_ORDER has been assigned an invalid value."
 #endif
 
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #if (SB_API_VERSION < 12 && !defined(SB_HAS_MICROPHONE))
 #error \
     "Your platform must define SB_HAS_MICROPHONE in API versions 11 or earlier."
 #endif
 
-#if SB_API_VERSION < SB_TIME_THREAD_NOW_REQUIRED_VERSION && \
-    !defined(SB_HAS_TIME_THREAD_NOW)
+#if SB_API_VERSION < 12 && !defined(SB_HAS_TIME_THREAD_NOW)
 #error \
     "Your platform must define SB_HAS_TIME_THREAD_NOW in API versions 3 to 11."
 #endif
@@ -1001,7 +776,7 @@
 #error "Your platform must define SB_HAS_NV12_TEXTURE_SUPPORT."
 #endif
 
-#if SB_API_VERSION >= SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER_DEPRECATED_VERSION
+#if SB_API_VERSION >= 12
 #if defined(SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER)
 #error "SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER is deprecated."
 #error "Use `CobaltExtensionGraphicsApi` instead."
@@ -1013,7 +788,7 @@
 #endif
 #endif
 
-#if SB_API_VERSION >= SB_FEATURE_GYP_CONFIGURATION_VERSION
+#if SB_API_VERSION >= 12
 #if defined(COBALT_MAX_CPU_USAGE_IN_BYTES)
 #error "|max_cobalt_cpu_usage| is deprecated "
 #error "SbSystemGetTotalCPUMemory() instead."
@@ -1022,7 +797,7 @@
 #error "|max_cobalt_gpu_usage| is deprecated. "
 #error "Implement SbSystemGetTotalGPUMemory() instead."
 #endif
-#endif  // SB_API_VERSION >= SB_FEATURE_GYP_CONFIGURATION_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #if defined(COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET)
 #error "COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET is deprecated."
@@ -1044,7 +819,8 @@
 #error "COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS"
 #error "is deprecated. Implement"
 #error "|SbMediaGetBufferGarbageCollectionDurationThreshold| instead."
-#endif  // defined(COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS)
+#endif  // defined(
+// COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS)
 
 #if defined(COBALT_MEDIA_BUFFER_PADDING)
 #error "COBALT_MEDIA_BUFFER_PADDING is deprecated."
@@ -1141,12 +917,11 @@
 #endif  // SB_API_VERSION < SB_SPEECH_RECOGNIZER_IS_REQUIRED && SB_API_VERSION
         // >= 5
 
-#if SB_API_VERSION < SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION && \
-    SB_API_VERSION >= 8
+#if SB_API_VERSION < 12 && SB_API_VERSION >= 8
 #if !defined(SB_HAS_ON_SCREEN_KEYBOARD)
 #error "Your platform must define SB_HAS_ON_SCREEN_KEYBOARD."
 #endif  // !defined(SB_HAS_ON_SCREEN_KEYBOARD)
-#endif  // SB_API_VERSION < SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION &&
+#endif  // SB_API_VERSION < 12 &&
         // SB_API_VERSION >= 8
 
 #if SB_HAS(ON_SCREEN_KEYBOARD) && (SB_API_VERSION < 8)
@@ -1158,11 +933,12 @@
 #endif  // defined(SB_HAS_PLAYER_FILTER_TESTS)
 
 #if defined(SB_HAS_PLAYER_ERROR_MESSAGE)
-#error "SB_HAS_PLAYER_ERROR_MESSAGE should not be defined in API versions >= 10."
+#error \
+    "SB_HAS_PLAYER_ERROR_MESSAGE should not be defined in API versions " \
+       ">= 10."
 #endif  // defined(SB_HAS_PLAYER_ERROR_MESSAGE)
 
-#if SB_API_VERSION >= \
-    SB_PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT_VERSION
+#if SB_API_VERSION >= 12
 #if defined(SB_HAS_PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 #if !SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 #error \
@@ -1172,8 +948,7 @@
 #else   // defined(SB_HAS_PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 #define SB_HAS_PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT 1
 #endif  // defined(SB_HAS_PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-#endif  // SB_API_VERSION >=
-        // SB_PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 #if SB_API_VERSION < 11
@@ -1183,7 +958,7 @@
 #endif  // SB_API_VERSION < 11
 #endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 
-#if SB_API_VERSION >= SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
+#if SB_API_VERSION >= 12 && SB_HAS(BLITTER)
 #error \
     "Blitter API is no longer supported. All blitter functions in " \
 "'starboard/blitter.h' are deprecated."
@@ -1191,7 +966,7 @@
 
 // --- Derived Configuration -------------------------------------------------
 
-#if SB_API_VERSION < SB_SABI_FILE_VERSION
+#if SB_API_VERSION < 12
 
 // Whether the current platform is little endian.
 #if SB_IS(BIG_ENDIAN)
@@ -1200,7 +975,7 @@
 #define SB_IS_LITTLE_ENDIAN 1
 #endif
 
-#endif  // SB_API_VERSION < SB_SABI_FILE_VERSION
+#endif  // SB_API_VERSION < 12
 
 // Whether the current platform has 64-bit atomic operations.
 #if SB_IS(64_BIT)
@@ -1228,8 +1003,7 @@
 
 // Specifies whether this platform has any kind of supported graphics system.
 #if !defined(SB_HAS_GRAPHICS)
-#if SB_HAS(GLES2) || SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || \
-    SB_HAS(BLITTER)
+#if SB_HAS(GLES2) || SB_API_VERSION >= 12 || SB_HAS(BLITTER)
 #define SB_HAS_GRAPHICS 1
 #else
 #define SB_HAS_GRAPHICS 0
diff --git a/src/starboard/configuration_constants.h b/src/starboard/configuration_constants.h
index 8e6c27d..961affe 100644
--- a/src/starboard/configuration_constants.h
+++ b/src/starboard/configuration_constants.h
@@ -23,7 +23,7 @@
 
 #include "starboard/types.h"
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
 
 // Determines the threshhold of allocation size that should be done with mmap
 // (if available), rather than allocated within the core heap.
@@ -61,9 +61,6 @@
 // Allow ac3 and ec3 support
 extern const bool kSbHasAc3Audio;
 
-// Specifies whether this platform updates audio frames asynchronously.
-extern const bool kSbHasAsyncAudioFramesReporting;
-
 // Specifies whether this platform has webm/vp9 support.  This should be set to
 // non-zero on platforms with webm/vp9 support.
 extern const bool kSbHasMediaWebmVp9Support;
@@ -163,6 +160,6 @@
 // The maximum number of users that can be signed in at the same time.
 extern const uint32_t kSbUserMaxSignedIn;
 
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #endif  // STARBOARD_CONFIGURATION_CONSTANTS_H_
diff --git a/src/starboard/contrib/creator/ci20x11/gyp_configuration.py b/src/starboard/contrib/creator/ci20x11/gyp_configuration.py
index 75d9285..b612663 100644
--- a/src/starboard/contrib/creator/ci20x11/gyp_configuration.py
+++ b/src/starboard/contrib/creator/ci20x11/gyp_configuration.py
@@ -28,10 +28,10 @@
   def __init__(self, platform_name='creator-ci20x11'):
     super(CreatorCI20X11Configuration, self).__init__(platform_name)
 
-  def GetTargetToolchain(self):
-    return self.GetHostToolchain()
+  def GetTargetToolchain(self, **kwargs):
+    return self.GetHostToolchain(**kwargs)
 
-  def GetHostToolchain(self):
+  def GetHostToolchain(self, **kwargs):
     environment_variables = self.GetEnvironmentVariables()
     cc_path = environment_variables['CC']
     cxx_path = environment_variables['CXX']
diff --git a/src/starboard/contrib/creator/shared/configuration_public.h b/src/starboard/contrib/creator/shared/configuration_public.h
index ec1364b..fd0c46f 100644
--- a/src/starboard/contrib/creator/shared/configuration_public.h
+++ b/src/starboard/contrib/creator/shared/configuration_public.h
@@ -333,7 +333,7 @@
 
 // Whether this platform has and should use an MMAP function to map physical
 // memory to the virtual address space.
-#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#if SB_API_VERSION < 12
 #define SB_HAS_MMAP 1
 #endif
 
diff --git a/src/starboard/contrib/creator/shared/media_is_video_supported.cc b/src/starboard/contrib/creator/shared/media_is_video_supported.cc
index 8581bfa..7775b0c 100644
--- a/src/starboard/contrib/creator/shared/media_is_video_supported.cc
+++ b/src/starboard/contrib/creator/shared/media_is_video_supported.cc
@@ -31,9 +31,6 @@
                              int64_t bitrate,
                              int fps,
                              bool decode_to_texture_required) {
-  SB_UNREFERENCED_PARAMETER(profile);
-  SB_UNREFERENCED_PARAMETER(level);
-
   using starboard::shared::starboard::media::IsSDRVideo;
 
   if (!IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id)) {
diff --git a/src/starboard/contrib/linux/x64wl/gyp_configuration.py b/src/starboard/contrib/linux/x64wl/gyp_configuration.py
index 4502908..3d6687a 100644
--- a/src/starboard/contrib/linux/x64wl/gyp_configuration.py
+++ b/src/starboard/contrib/linux/x64wl/gyp_configuration.py
@@ -32,10 +32,10 @@
     super(LinuxX64WaylandConfiguration, self).__init__(
         platform_name, asan_enabled_by_default, goma_supports_compiler)
 
-  def GetTargetToolchain(self):
-    return self.GetHostToolchain()
+  def GetTargetToolchain(self, **kwargs):
+    return self.GetHostToolchain(**kwargs)
 
-  def GetHostToolchain(self):
+  def GetHostToolchain(self, **kwargs):
     environment_variables = self.GetEnvironmentVariables()
     cc_path = environment_variables['CC']
     cxx_path = environment_variables['CXX']
diff --git a/src/starboard/contrib/tizen/shared/alsa/alsa_audio_sink_type.cc b/src/starboard/contrib/tizen/shared/alsa/alsa_audio_sink_type.cc
index 9e6bf7c..12d0e47 100644
--- a/src/starboard/contrib/tizen/shared/alsa/alsa_audio_sink_type.cc
+++ b/src/starboard/contrib/tizen/shared/alsa/alsa_audio_sink_type.cc
@@ -332,9 +332,9 @@
         consumed = 0;
       consume_frame_func_(
           consumed,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
           (SbTime)kSbTimeMax,  // Async audio frames reporting not supported
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif // SB_API_VERSION >= 12
           context_);
       if (consumed != frames_to_buffer_end) {
         return;
@@ -354,9 +354,9 @@
     }
     consume_frame_func_(
         consumed,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
         (SbTime)kSbTimeMax,  // Async audio frames reporting not supported
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif // SB_API_VERSION >= 12
         context_);
   } else {
     // A very low quality resampler that simply shift the audio frames to play
@@ -391,9 +391,9 @@
     }
     consume_frame_func_(
         consumed * playback_rate_,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
         (SbTime)kSbTimeMax,  // Async audio frames reporting not supported
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif // SB_API_VERSION >= 12
         context_);
   }
 }
diff --git a/src/starboard/contrib/tizen/shared/configuration_public.h b/src/starboard/contrib/tizen/shared/configuration_public.h
index 7ccf2cb..0fd9c33 100644
--- a/src/starboard/contrib/tizen/shared/configuration_public.h
+++ b/src/starboard/contrib/tizen/shared/configuration_public.h
@@ -180,7 +180,7 @@
 
 // Whether this platform has and should use an MMAP function to map physical
 // memory to the virtual address space.
-#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#if SB_API_VERSION < 12
 #define SB_HAS_MMAP 1
 #endif
 
diff --git a/src/starboard/contrib/tizen/shared/log/log.cc b/src/starboard/contrib/tizen/shared/log/log.cc
index ca006ec..774d7bc 100644
--- a/src/starboard/contrib/tizen/shared/log/log.cc
+++ b/src/starboard/contrib/tizen/shared/log/log.cc
@@ -31,7 +31,6 @@
 #define LOG_TAG "COBALT"
 
 void SbLog(SbLogPriority priority, const char* message) {
-  SB_UNREFERENCED_PARAMETER(priority);
   log_priority dlog_priority = DLOG_UNKNOWN;
 
   switch (priority) {
diff --git a/src/starboard/cpu_features.h b/src/starboard/cpu_features.h
index c204ac4..fced92a 100644
--- a/src/starboard/cpu_features.h
+++ b/src/starboard/cpu_features.h
@@ -192,10 +192,10 @@
 
   // SSE3 extensions.
   bool has_sse3;
-#if defined(SB_CPU_FEATURE_PCLMULQDQ)
+#if SB_API_VERSION >= 12
   // PCLMULQDQ instruction.
   bool has_pclmulqdq;
-#endif  // defined(SB_CPU_FEATURE_PCLMULQDQ)
+#endif  // SB_API_VERSION >= 12
   // Supplemental SSE3 extensions.
   bool has_ssse3;
   // SSE-4.1 extensions.
diff --git a/src/starboard/cryptography.h b/src/starboard/cryptography.h
index 3edc4ba..32e3aac 100644
--- a/src/starboard/cryptography.h
+++ b/src/starboard/cryptography.h
@@ -54,7 +54,7 @@
 #include "starboard/export.h"
 #include "starboard/types.h"
 
-#if SB_API_VERSION >= SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION >= 12
 #error "Starboard Crypto API is deprecated"
 #else
 
@@ -230,6 +230,6 @@
 }  // extern "C"
 #endif
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #endif  // STARBOARD_CRYPTOGRAPHY_H_
diff --git a/src/starboard/decode_target.h b/src/starboard/decode_target.h
index cb7576e..a06509e 100644
--- a/src/starboard/decode_target.h
+++ b/src/starboard/decode_target.h
@@ -96,9 +96,9 @@
 #include "starboard/export.h"
 #include "starboard/types.h"
 
-#if SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
+#if SB_API_VERSION < 12 && SB_HAS(BLITTER)
 #include "starboard/blitter.h"
-#endif  // SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
+#endif  // SB_API_VERSION < 12 && SB_HAS(BLITTER)
 
 #ifdef __cplusplus
 extern "C" {
@@ -175,7 +175,7 @@
   kSbDecodeTargetPlaneV = 2,
 } SbDecodeTargetPlane;
 
-#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
+#if SB_API_VERSION >= 12 || SB_HAS(GLES2)
 struct SbDecodeTargetGraphicsContextProvider;
 
 // Signature for a Starboard implementaion function that is to be run by a
@@ -191,7 +191,7 @@
     struct SbDecodeTargetGraphicsContextProvider* graphics_context_provider,
     SbDecodeTargetGlesContextRunnerTarget target_function,
     void* target_function_context);
-#endif  // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(GLES2)
 
 // In general, the SbDecodeTargetGraphicsContextProvider structure provides
 // information about the graphics context that will be used to render
@@ -201,12 +201,12 @@
 // should be provided to all Starboard functions that might create
 // SbDecodeTargets (e.g. SbImageDecode()).
 typedef struct SbDecodeTargetGraphicsContextProvider {
-#if SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
+#if SB_API_VERSION < 12 && SB_HAS(BLITTER)
   // The SbBlitterDevice object that will be used to render any produced
   // SbDecodeTargets.
   SbBlitterDevice device;
 #endif
-#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
+#if SB_API_VERSION >= 12 || SB_HAS(GLES2)
   // A reference to the EGLDisplay object that hosts the EGLContext that will
   // be used to render any produced SbDecodeTargets.  Note that it has the
   // type |void*| in order to avoid #including the EGL header files here.
@@ -225,10 +225,10 @@
   // Context data that is to be passed in to |gles_context_runner| when it is
   // invoked.
   void* gles_context_runner_context;
-#elif !(SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER))
+#elif !(SB_API_VERSION >= 12 || SB_HAS(BLITTER))
   // Some compilers complain about empty structures, this is to appease them.
   char dummy;
-#endif  // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(GLES2)
 } SbDecodeTargetGraphicsContextProvider;
 
 // Defines a rectangular content region within a SbDecodeTargetInfoPlane
@@ -256,11 +256,11 @@
 
 // Defines an image plane within a SbDecodeTargetInfo object.
 typedef struct SbDecodeTargetInfoPlane {
-#if SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
+#if SB_API_VERSION < 12 && SB_HAS(BLITTER)
   // A handle to the Blitter surface that can be used for rendering.
   SbBlitterSurface surface;
-#endif  // SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
-#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
+#endif  // SB_API_VERSION < 12 && SB_HAS(BLITTER)
+#if SB_API_VERSION >= 12 || SB_HAS(GLES2)
   // A handle to the GL texture that can be used for rendering.
   uint32_t texture;
 
@@ -278,7 +278,7 @@
   uint32_t gl_texture_format;
 #endif  // SB_API_VERSION >= 7
 
-#endif  // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(GLES2)
 
   // The width of the texture/surface for this particular plane.
   int width;
diff --git a/src/starboard/directory.h b/src/starboard/directory.h
index e75e56c..65be54f 100644
--- a/src/starboard/directory.h
+++ b/src/starboard/directory.h
@@ -34,13 +34,13 @@
 // A handle to an open directory stream.
 typedef struct SbDirectoryPrivate* SbDirectory;
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Represents a directory entry.
 typedef struct SbDirectoryEntry {
   // The name of this directory entry.
   char name[SB_FILE_MAX_NAME];
 } SbDirectoryEntry;
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
 // Well-defined value for an invalid directory stream handle.
 #define kSbDirectoryInvalid ((SbDirectory)NULL)
@@ -66,10 +66,14 @@
 // |directory|: The directory stream handle to close.
 SB_EXPORT bool SbDirectoryClose(SbDirectory directory);
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
 // Populates |out_entry| with the next entry in the specified directory stream,
 // and moves the stream forward by one entry.
 //
+// Platforms may, but are not required to, return |.| (referring to the
+// directory itself) and/or |..| (referring to the directory's parent directory)
+// as entries in the directory stream.
+//
 // This function returns |true| if there was a next directory, and |false|
 // at the end of the directory stream or if |out_entry_size| is smaller than
 // kSbFileMaxName.
@@ -83,10 +87,14 @@
 SB_EXPORT bool SbDirectoryGetNext(SbDirectory directory,
                                   char* out_entry,
                                   size_t out_entry_size);
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else   // SB_API_VERSION >= 12
 // Populates |out_entry| with the next entry in the specified directory stream,
 // and moves the stream forward by one entry.
 //
+// Platforms may, but are not required to, return |.| (referring to the
+// directory itself) and/or |..| (referring to the directory's parent directory)
+// as entries in the directory stream.
+//
 // This function returns |true| if there was a next directory, and |false|
 // at the end of the directory stream.
 //
@@ -94,7 +102,7 @@
 // |out_entry|: The variable to be populated with the next directory entry.
 SB_EXPORT bool SbDirectoryGetNext(SbDirectory directory,
                                   SbDirectoryEntry* out_entry);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
 
 // Indicates whether SbDirectoryOpen is allowed for the given |path|.
 //
diff --git a/src/starboard/doc/evergreen/cobalt_evergreen_overview.md b/src/starboard/doc/evergreen/cobalt_evergreen_overview.md
new file mode 100644
index 0000000..ccf031e
--- /dev/null
+++ b/src/starboard/doc/evergreen/cobalt_evergreen_overview.md
@@ -0,0 +1,477 @@
+# Cobalt Evergreen Overview
+
+![Cobalt non-Evergreen vs
+Evergreen](resources/cobalt_evergreen_overview_flow.png)
+
+## What is Cobalt Evergreen?
+
+Cobalt Evergreen is an end-to-end framework for cloud-based deployment of Cobalt
+updates without the need for supplemental Cobalt integration work on device
+platforms.
+
+For a bit of background context, as the number of Cobalt devices in the field
+increases there is a growing proliferation of version fragmentation. Many of
+these devices are unable to take advantage of the benefits of Cobalt
+performance, security, and functional improvements as it is costly to integrate
+and port new versions of Cobalt. We recognized this issue, listened to feedback
+from the Cobalt community and as a result developed Cobalt Evergreen as a way to
+make updating Cobalt a much simpler process for everyone involved.
+
+This relies on separating the Starboard(platform) and Cobalt(core) components of
+a Cobalt implementation into the following discrete components:
+
+**Google-built** (on Google toolchain)
+
+*   Cobalt Core
+    *   Pre-built shared library available for all supported architectures
+*   Cobalt Updater
+    *   Part of Cobalt Core and used to query servers to check for and download
+        updated Cobalt Core
+
+**Partner-built** (on Partner toolchain)
+
+*   Starboard
+    *   Platform-specific implementation
+    *   Contains system dependencies (e.g. `libpthread.so`, `libEGL.so`)
+*   Cobalt Loader (Loader App)
+    *   Selects the appropriate Cobalt core for usage
+    *   An ELF loader is used to load the Cobalt core and resolves symbols with
+        Starboard APIs when Cobalt starts up in Evergreen mode
+
+With this new Cobalt platform architecture, less engineering effort is necessary
+for a full Cobalt integration/deployment. The idea here is you should only need
+to implement Starboard one time and any Cobalt-level updates should only require
+platform testing. NOTE that certain new Cobalt features may require Starboard
+changes, so if you want to take advantage of some of these new features,
+Starboard changes may be necessary.
+
+### Main Benefits
+
+*   More stable platform as there is less Cobalt version fragmentation
+*   Little-to-no engineering effort necessary for Cobalt updates
+*   Longer device lifetime due to more Cobalt updates
+*   Less engineering work/accelerated timeline for Cobalt integration/deployment
+    as Google builds the Cobalt components and partners are only responsible for
+    the Starboard and `loader_app` portion
+
+### New in Evergreen
+
+*   Larger storage and system permissions requirements in order to update and
+    store multiple Cobalt binaries
+*   Access permissions to download binaries onto a device platform from Google
+    servers
+*   New `loader_app` component required to be built on platform toolchains
+*   Additional testing/verification required to ensure new Cobalt releases work
+    properly
+
+## How is Evergreen different from porting Cobalt previously?
+
+There are minimal differences in switching to Evergreen as the Cobalt team has
+already done a majority of the work building the necessary components to support
+the Evergreen architecture. You will still be responsible for building the
+Starboard and platform-specific components as usual. Thereafter, switching to
+Evergreen is as simple as building a different configuration. Please see the
+Raspberry Pi 2 Evergreen reference port
+([Instructions](cobalt_evergreen_reference_port_raspi2.md)) for an example.
+
+![Cobalt non-Evergreen vs
+Evergreen](resources/cobalt_evergreen_overview_vs_non_evergreen.png)
+
+### Building Cobalt Evergreen Components
+
+Cobalt Evergreen requires that there are two separate build(`gyp`)
+configurations used due to the separation of the Cobalt core(`libcobalt.so`) and
+the platform-specific Starboard layer(`loader_app`). As a result, you will have
+to initiate a separate gyp process for each. This is required since the Cobalt
+core binary is built with the Google toolchain settings and the
+platform-specific Starboard layer is built with partner toolchain
+configurations.
+
+Cobalt Evergreen is built by a separate gyp platform using the Google toolchain:
+
+```
+$ cobalt/build/gyp_cobalt evergreen-arm-softfp-sbversion-12
+$ ninja -C out/evergreen-arm-softfp-sbversion-12_qa cobalt
+```
+
+Which produces a shared library `libcobalt.so` targeted for specific
+architecture, ABI and Starboard version.
+
+The gyp variable `sb_evergreen` is set to 1 when building `libcobalt.so`.
+
+The partner port of Starboard is built with the partner’s toolchain and is
+linked into the **`loader_app` which knows how to dynamically load
+`libcobalt.so`.
+
+```
+cobalt/build/gyp_cobalt <partner_port_name>
+ninja -C out/<partner_port_name>_qa loader_app
+```
+
+Partners should set `sb_evergreen_compatible` to 1 in their gyp platform config.
+DO NOT set the `sb_evergreen` to 1 in your platform-specific configuration as it
+is used only by Cobalt when building with the Google toolchain.
+
+The following additional Starboard interfaces are necessary to implement for
+Evergreen:
+
+*   `kSbSystemPathStorageDirectory`
+    *   Dedidated location for storing Cobalt Evergreen-related binaries
+    *   This path must be writable and have at least 96MB of reserved space for
+        Evergreen updates. Please see the “Platforms Requirements” section below
+        for more details.
+*   `kSbMemoryMapProtectExec`
+    *   Ensures mapped memory can be executed
+*   `#define SB_CAN_MAP_EXECUTABLE_MEMORY 1`
+    *   Specifies that the platform can map executable memory
+    *   Defined in `configuration_public.h`
+
+Only if necessary, create a customized SABI configuration for your architecture.
+Note, we do not anticipate that you will need to make a new configuration for
+your platform unless it is not one of our supported architectures:
+
+*   x86\_32
+*   x86\_64
+*   arm32
+*   arm64
+
+If your target architecture falls outside the support list above, please reach
+out to us for guidance.
+
+### What is an example for how this would help me?
+
+Some common versions of Cobalt in the field may show a bug in the implementation
+of the CSS which can cause layout behavior to cause components to overlap and
+give users a poor user experience. A fix for this is identified and pushed to
+Cobalt open source ready for integration and deployment on devices.
+
+#### Without Cobalt Evergreen:
+
+Though a fix for this was made available in the latest Cobalt open source,
+affected devices in the field are not getting updated (e.g. due to engineering
+resources, timing, device end-of-life), users continue to have a poor experience
+and have negative sentiment against a device. In parallel, the web app team
+determines a workaround for this particular situation, but the workaround is
+obtuse and causes app bloat and technical debt from on-going maintenance of
+workarounds for various Cobalt versions.
+
+#### With Cobalt Evergreen:
+
+The Cobalt team can work with you to guide validation and deployment of a shared
+Cobalt library to all affected devices much more quickly without all the
+engineering effort required to deploy a new Cobalt build. With this simpler
+updating capability, device behavior will be more consistent and there is less
+technical debt from workarounds on the web application side. Additionally, users
+can benefit from the latest performance, security, and functional fixes.
+
+## Platform Requirements
+
+Cobalt Evergreen currently supports the following
+
+Target Architectures:
+
+*   x86\_32
+*   x86\_64
+*   armv7 32
+*   armv8 64
+
+Supported Javascript Engines
+
+*   V8
+
+Additional reserved storage (96MB) is required for Evergreen binaries. We expect
+Evergreen implementations to have an initial Cobalt preloaded on the device and
+an additional reserved space for additional Cobalt update storage.
+
+*   Initial Cobalt binary deployment - 64MB
+*   Additional Cobalt update storage - 96MB
+    *   Required for 2 update slots under `kSbSystemPathStorageDirectory`
+
+As Cobalt Evergreen is intended to be updated from Google Cloud architecture
+without the need for device FW updates, it is important that this can be done
+easily and securely on the target platform. There are a set of general minimum
+requirements to do so:
+
+*   Writable access to the file system of a device platform to download Cobalt
+    Evergreen binaries
+*   Enough reserved storage for Cobalt updates
+*   Platform supporting mmap API with writable memory (`PROT_WRITE`,
+    `PROT_EXEC`) for loading in-memory and performing relocations for Cobalt
+    Evergreen binaries
+
+## Verifying Platform Requirements
+
+In order to verify the platform requirements you should run the
+‘nplb\_evergreen\_compat\_tests’. These tests ensure that the platform is
+configured appropriately for Evergreen.
+
+To enable the test, set the `sb_evergreen_compatible gyp` variable to 1 in the
+`gyp_configuration.gypi`. For more details please take a look at the Raspberry
+Pi 2 gyp files.
+
+There is a reference implementation available for Raspberry Pi 2 with
+instructions available [here](cobalt_evergreen_reference_port_raspi2.md).
+
+## System Design
+
+![Cobalt Evergreen
+Components](resources/cobalt_evergreen_overview_components.png)
+
+The above diagram is a high-level overview of the components in the Cobalt
+Evergreen architecture.
+
+* **Partner-built** represents components the Partner is responsible for
+  implementing and building.
+
+* **Cobalt-built** represents components the Cobalt team is responsible for
+  implementing and building.
+
+### Cobalt Evergreen Components
+
+#### Cobalt Updater
+
+This is a new component in the Cobalt Shared Library component that is built on
+top of the Starboard API. The purpose of this module is to check the update
+servers if there is a new version of the Cobalt Shared Library available for the
+target device. If a new version is available, the Cobalt updater will download,
+verify, and install the new package on the target platform. The new package can
+be used the next time Cobalt is started or it can be forced to update
+immediately and restart Cobalt as soon as the new package is available and
+verified on the platform. This behavior will take into account the
+suspend/resume logic on the target platform.
+
+Functionally, the Cobalt Updater itself runs as a separate thread within the
+Cobalt process when Cobalt is running. This behavior depends on what the target
+platform allows.
+
+For more detailed information on Cobalt Updater, please take a look
+[here](cobalt_update_framework.md).
+
+#### Google Update (Update Server)
+
+We use Google Update as the infrastructure to manage the Cobalt Evergreen
+package install and update process. This has been heavily used across Google for
+quite some time and has the level of reliability required for Cobalt Evergreen.
+There are also other important features such as:
+
+*   Fine grained device targeting
+*   Rollout and rollback
+*   Multiple update channels (e.g. production, testing, development)
+*   Staged rollouts
+
+For more detailed information on Google Update for Cobalt Evergreen, please take
+a look [here](cobalt_update_framework.md).
+
+#### Google Downloads (Download Server)
+
+We use Google Downloads to manage the downloads available for Cobalt Evergreen.
+The Cobalt Updater will use Google Downloads in order to download available
+packages onto the target platform. We selected Google Downloads for this purpose
+due to its ability to scale across billions of devices as well as the
+flexibility to control download behavior for reliability.
+
+For more detailed information on Google Downloads (Download Server) for Cobalt
+Evergreen, please take a look [here](cobalt_update_framework.md).
+
+### Cobalt Evergreen Interfaces
+
+#### Starboard ABI
+
+The Starboard ABI was introduced to provide a single, consistent method for
+specifying the Starboard API version and the ABI. This specification ensures
+that any two binaries, built with the same Starboard ABI and with arbitrary
+toolchains, are compatible.
+
+Note that Cobalt already provides default SABI files for the following
+architectures:
+
+*   x86\_32
+*   x86\_64
+*   arm v7 (32-bit)
+*   arm v8 (64-bit)
+
+You should not need to make a new SABI file for your target platform unless it
+is not a currently supported architecture. We recommend that you do not make any
+SABI file changes. If you believe it is necessary to create a new SABI file for
+your target platform, please reach out to the Cobalt team to advise.
+
+For more detailed information on the Starboard ABI for Cobalt Evergreen, please
+take a look here.
+
+### Installation Slots
+
+Cobalt Evergreen provides support for maintaining multiple separate versions of
+the Cobalt binary on a platform. These versions are stored in installation
+slots(i.e. known locations on disk), and are used to significantly improve the
+resilience and reliability of Cobalt updates.
+
+The number of installation slots available will be determined by the platform
+owner. A minimum of 2 must be available with the limit being the storage
+available on the platform.
+
+It is worth noting that adding a third installation slot allows a factory image
+to be permanently installed as a fail-safe option.
+
+The number of installation slots is directly controlled using
+`kMaxNumInstallations`, defined in
+[loader\_app.cc](https://cobalt.googlesource.com/cobalt/+/refs/heads/master/src/starboard/loader_app/loader_app.cc).
+
+There are subtle differences between using 2 installation slots and using 3 or
+more installation slots outlined below.
+
+#### 2 Slot Configuration
+
+Both of the installation slots are located in the directory specified by
+`kSbSystemPathStorageDirectory`. This will vary depending on the platform.
+
+On the Raspberry Pi this value will be `/home/pi/.cobalt_storage`. The paths to
+the installation slots will be as follows:
+
+`/home/pi/.cobalt_storage/installation_0` (initial installation slot)
+
+```
+/home/pi/.cobalt_storage/installation_1
+```
+
+Where the most recent update is stored will alternate between the two available
+slots. No factory image is maintained with this configuration so only the two
+most recent updates will be stored on the machine.
+
+Finally, the installation slot that will be used when Cobalt Evergreen is run
+would be stored in
+
+`/home/pi/.cobalt_storage/installation_store.pb` on the Raspberry Pi.
+
+#### 3+ Slot Configuration
+
+The 3+ slot configuration is very similar to the 2 slot configuration, but has
+one major difference: the original installation is maintained, and is stored in
+a read-only installation slot within the content directory.
+
+On the Raspberry Pi, the installation slots will be as follows:
+
+`/home/pi/path-to-cobalt/content/app/cobalt` (initial installation slot)
+(read-only)
+
+```
+/home/pi/.cobalt_storage/installation_1
+/home/pi/.cobalt_storage/installation_2
+```
+
+Similar to the 2 slot configuration, where the most recent update is stored will
+alternate between the two available slots (not the read-only installation slot).
+
+The installation slot that will be used when Cobalt Evergreen is run is
+determined, and stored, exactly the same as it is for the 2 slot configuration.
+
+### Fonts
+The system font directory `kSbSystemPathStorageDirectory` should be configured to
+point to the `standard` (23MB) or the `limited` (3.1MB) cobalt font packages. An
+easy way to do that is to use the `loader_app/content` directory and setting the
+`cobalt_font_package` to `standard` or `limited` in your port.
+
+Cobalt Evergreen, built by Google, will by default use the `minimal` cobalt
+package which is around 16KB to minimize storage requirements. A separate
+`cobalt_font_package` variable is set to `minimal` in the Evergreen platform.
+
+On Raspberry Pi this is:
+
+`minimal` set of fonts under:
+```
+~/.cobalt_storage/installation_0/content/fonts/
+```
+
+`standard` or `limited` set of fonts under:
+```
+loader_app/content/fonts
+```
+
+### ICU Tables
+The ICU table should be deployed under the kSbSystemPathStorageDirectory.
+This way all Cobalt Evergreen installations would be able to share the same
+tables. The current storage size for the ICU tables is 7MB.
+
+On Raspberry Pi this is:
+
+```
+/home/pi/.cobalt_storage/icu
+```
+The Cobalt Evergreen package will not carry ICU tables by default but may add
+them in the future if needed. When the package has ICU tables they would be
+stored under the content location for the installation.
+
+### Platform Security
+
+As Cobalt binary packages ([CRX
+format](https://docs.google.com/document/d/1pAVB4y5EBhqufLshWMcvbQ5velk0yMGl5ynqiorTCG4/edit#heading=h.ke61kmpkapku))
+are downloaded from the Google Downloads server, the verification of the Cobalt
+update package is critical to the reliability of Cobalt Evergreen. There are
+mechanisms in place to ensure that the binary is verified and a chain of trust
+is formed. The Cobalt Updater is responsible for downloading the available
+Cobalt update package and verifies that the package is authored by Cobalt(and
+not an imposter), before trying to install the downloaded package.
+
+#### Understanding Verification
+
+![Cobalt Evergreen CRX
+Verification](resources/cobalt_evergreen_overview_crx_verification.png)
+
+In the above diagram, the Cobalt Updater downloads the update package if
+available, and parses the CRX header of the package for verification, before
+unpacking the whole package. A copy of the Cobalt public key is contained in the
+CRX header, so the updater retrieves the key and generates the hash of the key
+coming from the header of the package, say _Key_ _hash1_.
+
+At the same time, the updater has the hash of the Cobalt public key hard-coded
+locally, say _Key hash2_.
+
+The updater compares _Key hash1_ with _Key hash2._ If they match, verification
+succeeds.
+
+## **FAQ**
+
+### Can I host the binaries for Cobalt core myself to deploy on my devices?
+
+Not at this time. All Cobalt updates will be deployed through Google
+infrastructure. We believe Google hosting the Cobalt core binaries allows us to
+ensure a high-level of reliability and monitoring in case issues arise.
+
+### What is the performance impact of switching to Cobalt Evergreen?
+
+We expect performance to be similar to a standard non-Evergreen Cobalt port.
+
+### How can I ensure that Cobalt updates work well on our platform?
+
+Google will work closely with device partners to ensure that the appropriate
+testing is in place to prevent regressions.
+
+### Will there be tests provided to verify functionality and detect regression?
+
+Yes, there are tests available to help validate the implementation:
+
+*   NPLB tests to ensure all necessary APIs are implemented
+*   Cobalt Evergreen Test Plan to verify the functionality of all components and
+    use cases
+
+### How can I be sure that Cobalt space requirements will not grow too large for my system resources?
+
+The Cobalt team is focusing a large amount of effort to identify and integrate
+various methods to reduce the size of the Cobalt binary such as compression and
+using less fonts.
+
+### What if something goes wrong in the field? Can we rollback?
+
+Yes, this is one of the benefits of Evergreen. We can initiate an update from
+the server side that addresses problems that were undetected during full
+testing. There are a formal set of guidelines to verify an updated binary
+deployed to the device to ensure that it will work properly with no regressions
+that partners should follow to ensure that there are no regressions. In
+addition, it is also critical to do your own testing to exercise
+platform-specific behavior.
+
+### How can I be sure that Cobalt Evergreen will be optimized for my platform?
+
+Much of the optimization work remains in the Starboard layer and configuration
+so you should still expect good performance using Cobalt Evergreen. That being
+said, the Cobalt Evergreen configuration allows you to customize Cobalt features
+and settings as before.
diff --git a/src/starboard/doc/evergreen/cobalt_evergreen_reference_port_raspi2.md b/src/starboard/doc/evergreen/cobalt_evergreen_reference_port_raspi2.md
new file mode 100644
index 0000000..23494e2
--- /dev/null
+++ b/src/starboard/doc/evergreen/cobalt_evergreen_reference_port_raspi2.md
@@ -0,0 +1,113 @@
+# Cobalt Evergreen Raspi-2 Reference Port
+
+## Requirements
+
+*   Raspberry Pi 2 (image configured per
+    [instructions](https://cobalt.dev/development/setup-raspi.html) on
+    cobalt.dev)
+
+## Build instructions
+
+```
+## Clone the repository
+$ git clone https://cobalt.googlesource.com/cobalt
+
+## Build the loader app (new entry point)
+$ cd cobalt/src
+$ cobalt/build/gyp_cobalt -v raspi-2-sbversion-12 -C qa
+$ ninja -C out/raspi-2-sbversion-12_qa loader_app
+
+## Create package directory for Cobalt Evergreen
+$ export COEG_PATH=coeg
+$ cp out/raspi-2-sbversion-12_qa/loader_app $COEG_PATH
+
+## Create directory structure for the initial installation
+[2-slot configuration]
+$ mkdir -p  ~/.cobalt_storage/installation_0/
+$ cd  ~/.cobalt_storage/installation_0/
+
+[3-slot configuration]
+$ mkdir -p $COEG_PATH/content/app/cobalt
+$ cd $COEG_PATH/content/app/cobalt
+
+## Download package
+$ curl -L https://dl.google.com/cobalt/evergreen/latest/cobalt_arm-hardfp_qa.crx  -o cobalt.zip
+
+## Unpack content package
+$ unzip cobalt.zip
+$ rm cobalt.zip
+$ cd -
+```
+
+The following are the steps to build the Cobalt content that’s contained in the
+crx package. Note you only need to do this if you want to build the Cobalt
+shared library and supplementary components.
+
+```
+## Build Cobalt core locally
+$ cd cobalt/src
+$ cobalt/build/gyp_cobalt -v evergreen-arm-hardfp-sbversion-12 -C qa
+$ ninja -C out/evergreen-arm-hardfp-sbversion-12_qa cobalt
+
+## Copy the generated files to the package directory for Cobalt Evergreen
+$ cp -r out/evergreen-arm-hardfp-sbversion-12_qa/lib   $COEG_PATH/content/app/cobalt/
+$ cp -r out/evergreen-arm-hardfp-sbversion-12_qa/content   $COEG_PATH/content/app/cobalt/
+
+## Download the manifest file
+$ curl https://storage.googleapis.com/evergreen_public/latest/manifest.json -o $COEG_PATH/content/app/cobalt/manifest.json
+```
+
+## Deployment instructions
+
+Configure your Raspberry Pi 2 with the following steps from your Linux machine.
+
+```
+## Save the address of the device
+$ export RASPI_ADDR=<YOUR_RASPI_ID_ADDR>
+
+## Remove old storage directory
+$ rm -rf /home/pi/.cobalt_storage
+
+## Copy the Evergreen contents to the device
+$ rsync -arvp $COEG_PATH pi@$RASPI_ADDR:/home/pi
+
+## Launch
+$ ssh pi@$RASPI_ADDR  /home/pi/$COEG_PATH/loader_app
+```
+
+## Run instructions
+
+```
+$ ssh pi@$RASPI_ADDR
+$ cd coeg
+$ ./loader_app
+```
+
+Cobalt should load and work as usual, but leveraging Evergreen. That’s it!
+
+## Troubleshooting
+
+### Certificate errors on execution of loader\_app
+
+Certificate issues may occur on certain network environments when launching
+`loader_app` via SSH. In this case, try launching with a keyboard directly
+connected to the device.
+
+### “Failed to load library at <path>” thrown on startup
+
+The loader can’t find the `libcobalt.so` file. Check that the path to
+`libcobalt.so` completely matches the one in Deployment instructions.
+
+### “fatal error: “assert(sk\_file)”” thrown on startup
+
+The loader can’t find the content/data folder or it is malformed. Check that the
+path to this folder completely matches the one in Deployment instructions.
+
+### “Check failed: address. Failed to retrieve the address” thrown on startup
+
+Ensure that `libcobalt.so` being used is the correct version. For a rebuild, you
+may need to remove the old .cobalt\_storage directory on your device.
+
+```
+## Remove old storage directory
+$ rm -rf /home/pi/.cobalt_storage
diff --git a/src/starboard/doc/evergreen/cobalt_update_framework.md b/src/starboard/doc/evergreen/cobalt_update_framework.md
new file mode 100644
index 0000000..6ae81c0
--- /dev/null
+++ b/src/starboard/doc/evergreen/cobalt_update_framework.md
@@ -0,0 +1,100 @@
+# Cobalt Update Framework
+
+## Background
+
+The updatability of Cobalt on the field devices enables the deployment of new
+features and crucial bug fixes in a timely manner. It significantly reduces the
+amount of work on partners’ shoulders to update to a newer version of Cobalt.
+This document introduces how Cobalt updates itself and what the system is like
+that supports the update of Cobalt. Note that the Cobalt Update Framework is
+currently used only for Evergreen configurations.
+
+## Goal
+
+*   Enable Cobalt to automatically update itself periodically
+*   Build a framework that hosts and serves the updates reliably
+
+## Overview
+
+![Cobalt Update Overview](resources/cobalt_update_overview.png)
+
+The Cobalt Updater is a module of Cobalt. It is initiated as Cobalt starts. It
+periodically sends requests to Google Update server to check for updates. If an
+update is available, the Update server responds with a downloadable link of the
+update package to the Updater. Then the Updater connects to the link, which is
+hosted on Google Downloads server, to download the update package. If an update
+is not available, the Updater server responds to indicate no update. Then the
+Updater waits until the next scheduled time to check for updates again.
+
+## Implementation
+
+### Google Update
+
+![Cobalt Update Interaction](resources/cobalt_update_interaction.png)
+
+Google Update is an update service that manages updates for Google products
+serving billions of users worldwide. We set up Cobalt updates on Google Update
+in a way that each type of device gets a unique update link (URL). The device
+type is identified by [Starboard
+ABI](https://drive.google.com/a/google.com/open?id=1r1vS_FFMV9F-YlNaudxFwhAVG7delVleKfYgLLRUn3o)
+(SABI) string. For instance, Raspberry Pi 2 and Linux desktop are two different
+types of devices. They are identified by two different SABI strings, and get two
+different update URLs on Google Update. The request sent by the Cobalt updater
+to Google Update  contains a SABI string. Google Update finds the suitable
+update link that matches the SABI string from the request, and responds to the
+Cobalt updater.
+
+Google Update allows the setup of multiple channels. We set up different
+channels for internal testing, partner testing, production and developers.
+
+Google Update also allows staged rollout and rollback when things go wrong. In
+the case where a problem is detected that requires rollback or fixes, Google
+will work with the partner to find a path to resolution.
+
+### Google Downloads
+
+Google Downloads is a download hosting service for official Google content. We
+generate Cobalt update packages for various types of devices, and upload the
+packages to Google Downloads. Then the links to the packages on Google Downloads
+are served on Google Update.
+
+### Cobalt Updater
+
+The updater checks for updates on Google Downloads, then downloads the update
+package if available. After the download is complete, the updater verifies the
+downloaded package, then unpack the package to a designated installation
+location. The updater runs update checks following a predefined schedule: the
+first check happens after Cobalt starts; the second check runs in a randomized
+number of hours between 1 and 24 hours; the following checks run every 24 hours.
+
+### Update flow
+
+![Cobalt Update Flow](resources/cobalt_update_flow.png)
+
+Above is a chart of the workflow of a complete update cycle. It shows how the
+Updater operates step by step and how it interacts with the Installation Manager
+and the Elf Loader[^1].
+
+The Installation Manager maintains the installation slots and provides a proper
+slot to the Updater. During the update and installation process, the
+Installation Manager keeps track of the status and collects any installation
+error. After the installation is completed, the Installation Manager marks the
+installation as pending, so that next time Cobalt starts, the Elf Loader loads
+the new installation and the update is complete. If the target platform supports
+app exits/suspends on user exiting, Cobalt will exit when an installation is
+pending, so that the new update will be picked up on the next start; otherwise,
+Cobalt is not able to exit by itself, then a manual termination of the app is
+required to pick up the update on restart.
+
+## FAQ
+
+### What happens if an urgent problem is found that requires a rollback or update?
+
+In the case where a problem is detected that requires rollback or fixes, Google
+will work with the partner to find a path to resolution.
+
+<!-- Footnotes themselves at the bottom. -->
+## Footnotes
+
+[^1]: Elf loader - A portable loader that loads the Cobalt binary and resolves
+     symbols with Starboard API when Cobalt starts up in Evergreen mode.
diff --git a/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_components.png b/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_components.png
new file mode 100644
index 0000000..073ce92
--- /dev/null
+++ b/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_components.png
Binary files differ
diff --git a/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_crx_verification.png b/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_crx_verification.png
new file mode 100644
index 0000000..16ec0d9
--- /dev/null
+++ b/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_crx_verification.png
Binary files differ
diff --git a/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_flow.png b/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_flow.png
new file mode 100644
index 0000000..df0284b
--- /dev/null
+++ b/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_flow.png
Binary files differ
diff --git a/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_vs_non_evergreen.png b/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_vs_non_evergreen.png
new file mode 100644
index 0000000..cd9cb9f
--- /dev/null
+++ b/src/starboard/doc/evergreen/resources/cobalt_evergreen_overview_vs_non_evergreen.png
Binary files differ
diff --git a/src/starboard/doc/evergreen/resources/cobalt_update_flow.png b/src/starboard/doc/evergreen/resources/cobalt_update_flow.png
new file mode 100644
index 0000000..eebe1d3
--- /dev/null
+++ b/src/starboard/doc/evergreen/resources/cobalt_update_flow.png
Binary files differ
diff --git a/src/starboard/doc/evergreen/resources/cobalt_update_interaction.png b/src/starboard/doc/evergreen/resources/cobalt_update_interaction.png
new file mode 100644
index 0000000..07b710a
--- /dev/null
+++ b/src/starboard/doc/evergreen/resources/cobalt_update_interaction.png
Binary files differ
diff --git a/src/starboard/doc/evergreen/resources/cobalt_update_overview.png b/src/starboard/doc/evergreen/resources/cobalt_update_overview.png
new file mode 100644
index 0000000..3c8328e
--- /dev/null
+++ b/src/starboard/doc/evergreen/resources/cobalt_update_overview.png
Binary files differ
diff --git a/src/starboard/doc/resources/starboard_abi_overview.png b/src/starboard/doc/resources/starboard_abi_overview.png
new file mode 100644
index 0000000..8a15c74
--- /dev/null
+++ b/src/starboard/doc/resources/starboard_abi_overview.png
Binary files differ
diff --git a/src/starboard/doc/starboard_abi.md b/src/starboard/doc/starboard_abi.md
new file mode 100644
index 0000000..f97a788
--- /dev/null
+++ b/src/starboard/doc/starboard_abi.md
@@ -0,0 +1,119 @@
+# Starboard ABI
+
+The Starboard ABI was introduced to provide a single, consistent method for
+specifying the Starboard API version and the ABI. This specification ensures
+that any two binaries, built with the same Starboard ABI and with arbitrary
+toolchains, are compatible.
+
+## Background
+
+The Starboard ABI is the set of features, such as the Starboard API version or
+the sizes of data types, that collectively describes the relationship between
+the Starboard API and ABI of a binary. In the past, each of these features were
+inconsistently and ambiguously defined in a variety of files. This led to
+confusion, and made it difficult to track down the feature values for a
+platform. To simplify how Starboard is configured for a target platform, all of
+these features, and their concrete values, are now listed for each distinct
+target architecture in Starboard ABI files. These files provide a consistent,
+consolidated view of the values for each of these features, decoupling
+platform-specific details from architecture.
+
+## Goals
+
+The overall goal of the Starboard ABI is to provide a way to implement and
+verify binary compatibility on a target platform, and this goal can be broken
+down into the following more concise motivations:
+
+*   Separate platform and architecture into distinct concepts.
+*   Establish a consistent set of values for the various features of each target
+    architecture.
+*   Consolidate this set of features and their values in a consistent,
+    predictable location.
+*   Provide the ability to validate the values of each feature in produced
+    binaries.
+
+## Using Starboard ABI Files
+
+With the Starboard ABI being the source of truth for all things architecture
+related, each platform must now include a Starboard ABI file in its build (see
+[//starboard/sabi](https://cobalt.googlesource.com/cobalt/+/refs/heads/master/src/starboard/sabi)
+for examples). Starboard ABI files are JSON, and should all contain identical
+keys with the values being appropriate for the architecture. Each platform must
+override the new
+[GetPathToSabiJsonFile](https://cobalt.googlesource.com/cobalt/+/refs/heads/master/src/starboard/build/platform_configuration.py##339)
+method in its platform configuration to return the path to the desired Starboard
+ABI file (e.g.
+[//starboard/linux/shared/gyp\_configuration.py](https://cobalt.googlesource.com/cobalt/+/refs/heads/master/src/starboard/linux/shared/gyp_configuration.py)).
+By default, an empty and invalid Starboard ABI file is provided.
+
+Additionally, all platforms must include the
+[sabi.gypi](https://cobalt.googlesource.com/cobalt/+/refs/heads/master/src/starboard/sabi/sabi.gypi)
+in their build configuration. This file will consume the specified Starboard ABI
+file, resulting in the creation of a set of GYP variables and preprocessor
+macros. The preprocessor macros are passed directly to the compiler and replace
+the macros you might be familiar with, such as `SB_HAS_32_BIT_LONG`.
+
+The newly defined GYP variables need to be transformed into toolchain specific
+flags; these flags are what actually makes the build result in a binary for the
+desired architecture. These flags will, in most cases, be identical to the flags
+already being used for building. 
+
+The process outlined above is shown in the diagram below.
+
+![Starboard ABI Overview](resources/starboard_abi_overview.png)
+
+### Post-Starboard ABI File Cleanup
+
+A number of GYP variables and preprocessor macros should no longer be defined
+directly, and instead the Starboard ABI file will be used to define them. These
+definitions need to be removed.
+
+From `configuration_public.h`:
+
+*   `SB_IS_ARCH_*`
+*   `SB_IS_BIG_ENDIAN`
+*   `SB_IS_32_BIT`
+*   `SB_IS_64_BIT`
+*   `SB_HAS_32_BIT_LONG`
+*   `SB_HAS_64_BIT_LONG`
+*   `SB_HAS_32_BIT_POINTERS`
+*   `SB_HAS_64_BIT_POINTERS`
+
+From `gyp_configuration.gypi`:
+
+*   `target_arch`
+
+## FAQ
+
+### What Starboard ABI files are provided?
+
+The Cobalt team provides, and maintains, Starboard ABI files for the following
+architectures:
+
+*   x86\_32
+*   x86\_64
+*   ARM v7 (32-bit)
+*   ARM v8 (64-bit)
+
+If you find that no valid Starboard ABI file exists for your architecture, or
+that you need to change any values of a provided Starboard ABI file, please
+reach out to the Cobalt team to advise.
+
+### How can I verify that my build is configured correctly?
+
+Similar to the process prior to Starboard ABI files, there are multiple levels
+of verification that occur:
+
+1.  When configuring your build, the Starboard ABI file that was specified will
+    have its values sanity checked against a provided
+    [schema](https://cobalt.googlesource.com/cobalt/+/refs/heads/master/src/starboard/sabi/sabi.schema.json).
+1.  When building, a number of static assertions will assert correctness of a
+    number of features generated from the Starboard ABI file against the
+    features of the binary.
+1.  The NPLB test suite has been expanded to include [additional
+    tests](https://cobalt.googlesource.com/cobalt/+/refs/heads/master/src/starboard/nplb/sabi/)
+    capable of verifying the remaining features of the binary.
+
+Finally, binaries produced by the Cobalt team for your architecture, including
+NPLB, will be made available to ensure end-to-end correctness of the produced
+binaries.
\ No newline at end of file
diff --git a/src/starboard/doc/starboard_split.md b/src/starboard/doc/starboard_split.md
new file mode 100644
index 0000000..cab325c
--- /dev/null
+++ b/src/starboard/doc/starboard_split.md
@@ -0,0 +1,58 @@
+# Separation of Starboard from Cobalt
+
+### Background
+
+In creating Cobalt Evergreen, we needed to have as few differences in the code
+as we could from one platform to another. Simply put, that means we want to get
+rid of as many platform specific compile time macros as possible. Because of
+the large amount of platform differences we had previously, there were macros
+defined in a variety places, all of which require different cases to convert.
+The below sections go into the differences regarding changes to these macros
+from Cobalt 20 to 21 and from Starboard 11 to 12.
+
+## Optional APIs
+
+In previous versions, there were a few APIs that could optionally defined and
+would only be enabled if certain macros were set. The platform would only have
+to implement the API if it set the macros accordingly. Now, those differences
+have been removed, and all platforms are required to implement these APIs. For
+convenience, we have provided stub functions for all implementations, which a
+platform can use without differences in Cobalt if they did not enable the API
+beforehand.
+
+## Migration from Configuration Macros to External Constants
+
+Starboard configurations have moved from
+[configuration.h](../configuration.h) and platform specific
+`configuration_public.h` files to `configuration_constants.cc` files. They
+have also been changes from macros to `extern const`s. This means that Cobalt
+will be able to evaluate these variables at runtime instead of compile time.
+The declarations for all of these variables are located in
+[configuration_constants.h](../configuration_constants.h), but each platform
+must define each variable individually, i.e. as
+```
+// configuration_constants.cc
+#include "starboard/configuration_constants.h"
+
+const int32_t kSbFileMaxName = 64;
+```
+There are two changes that are a result of this migration:
+
+1. There is no longer any form of inheritance. This means that if there are any
+configuration differences between two platforms, they must have separate
+`configuration_constants.cc` files.
+2. There are no longer default values for any variable. Because we cannot
+inherit values, we would not be able to receive a default value for any one, so
+each platform must have a definition for every configuration variable.
+
+## Migration from GYP Variables to Cobalt Extensions
+
+Cobalt configurations have moved from [cobalt_configuration.gypi](../../cobalt/build/cobalt_configuration.gypi) and platform specific `gyp_configuration.gypi` files to Cobalt extensions, primarily [CobaltExtensionConfigurationApi](../../cobalt/extension/configuration.h), but including the [CobaltExtensionGraphicsApi](../../cobalt/extension/graphics.h).
+
+Some variables were already in the process of being deprecated, sometimes with a replacement. In those cases, that path was followed.
+
+Implementing the Cobalt extension is completely optional, and when calling the functions corresponding to the old GYP variable, there will be a default value that the function will be able to fall back onto if the extension has not been implemented. That being said, if there is a single function the platform needs a custom implementation for, it must completely implement the CobaltExtensionConfigurationApi. For convenience, we have provided default functions to use to define the API if desired.
+
+##### Notes
+
+For migrating from macros, partners will have to treat their use differently! I.e. string literal vs const char* in their implementations. Add an overview of all of the cases of this migration in runtime code.
\ No newline at end of file
diff --git a/src/starboard/drm.h b/src/starboard/drm.h
index 98e9b15..913ec18 100644
--- a/src/starboard/drm.h
+++ b/src/starboard/drm.h
@@ -83,7 +83,7 @@
   int identifier_size;
 } SbDrmKeyId;
 
-#if SB_API_VERSION >= SB_DRM_CBCS_SUPPORT_VERSION
+#if SB_API_VERSION >= 12
 
 // Encryption scheme of the input sample, as defined in ISO/IEC 23001 part 7.
 typedef enum SbDrmEncryptionScheme {
@@ -97,17 +97,17 @@
   uint32_t skip_byte_block;
 } SbDrmEncryptionPattern;
 
-#endif  // SB_API_VERSION >= SB_DRM_CBCS_SUPPORT_VERSION
+#endif  // SB_API_VERSION >= 12
 
 // All the optional information needed per sample for encrypted samples.
 typedef struct SbDrmSampleInfo {
-#if SB_API_VERSION >= SB_DRM_CBCS_SUPPORT_VERSION
+#if SB_API_VERSION >= 12
   // The encryption scheme of this sample.
   SbDrmEncryptionScheme encryption_scheme;
 
   // The encryption pattern of this sample.
   SbDrmEncryptionPattern encryption_pattern;
-#endif  // SB_API_VERSION >= SB_DRM_CBCS_SUPPORT_VERSION
+#endif  // SB_API_VERSION >= 12
 
   // The Initialization Vector needed to decrypt this sample.
   uint8_t initialization_vector[16];
@@ -366,6 +366,31 @@
                                             const void* certificate,
                                             int certificate_size);
 
+#if SB_API_VERSION >= 12
+// Get the metrics of the underlying drm system.
+//
+// When it is called on an implementation that supports drm system metrics, it
+// should return a pointer containing the metrics as a blob, encoded using url
+// safe base64 without padding and line wrapping, with the size of the encoded
+// result in |size| on return. For example, on Android API level 28 or later, it
+// should return the result of MediaDrm.getPropertyByteArray("metrics"), encoded
+// using url safe base64 without padding and line wrapping. On systems using
+// Widevine CE CDM with oemcrypto 16 or later, it should return the metrics
+// retrieved via Cdm::getMetrics(), encoded using url safe base64 without
+// padding and line wrapping.  The returned pointer should remain valid and its
+// content should remain unmodified until the next time this function is called
+// on the associated |drm_system| or the |drm_system| is destroyed.
+//
+// When the metrics is empty on supported system, it should return a non-null
+// pointer with |size| set to 0.
+//
+// It should return NULL when there is no metrics support in the underlying drm
+// system, or when the drm system implementation fails to retrieve the metrics.
+//
+// The caller will never set |size| to NULL.
+SB_EXPORT const void* SbDrmGetMetrics(SbDrmSystem drm_system, int* size);
+#endif  // SB_API_VERSION >= 12
+
 // Destroys |drm_system|, which implicitly removes all keys installed in it and
 // invalidates all outstanding session update requests. A DRM system cannot be
 // destroyed unless any associated SbPlayer or SbDecoder has first been
diff --git a/src/starboard/elf_loader/dynamic_section_test.cc b/src/starboard/elf_loader/dynamic_section_test.cc
index 6812046..3a8d55c 100644
--- a/src/starboard/elf_loader/dynamic_section_test.cc
+++ b/src/starboard/elf_loader/dynamic_section_test.cc
@@ -18,8 +18,7 @@
 #include "starboard/string.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if SB_API_VERSION >= 12 &&                                         \
-    (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+#if SB_API_VERSION >= 12 && (SB_API_VERSION >= 12 || SB_HAS(MMAP)) && \
     SB_CAN(MAP_EXECUTABLE_MEMORY)
 
 namespace starboard {
@@ -203,5 +202,5 @@
 }  // namespace
 }  // namespace elf_loader
 }  // namespace starboard
-#endif  // SB_API_VERSION >= 12 && (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION
+#endif  // SB_API_VERSION >= 12 && (SB_API_VERSION >= 12
         // || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/elf_header_test.cc b/src/starboard/elf_loader/elf_header_test.cc
index b2b94d2..b58c2a9 100644
--- a/src/starboard/elf_loader/elf_header_test.cc
+++ b/src/starboard/elf_loader/elf_header_test.cc
@@ -19,8 +19,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if SB_API_VERSION >= 12 &&                                         \
-    (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+#if SB_API_VERSION >= 12 && (SB_API_VERSION >= 12 || SB_HAS(MMAP)) && \
     SB_CAN(MAP_EXECUTABLE_MEMORY)
 namespace starboard {
 namespace elf_loader {
@@ -126,5 +125,5 @@
 }  // namespace
 }  // namespace elf_loader
 }  // namespace starboard
-#endif  // SB_API_VERSION >= 12 && (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION
+#endif  // SB_API_VERSION >= 12 && (SB_API_VERSION >= 12
         // || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/elf_loader.cc b/src/starboard/elf_loader/elf_loader.cc
index e86fb77..780edd7 100644
--- a/src/starboard/elf_loader/elf_loader.cc
+++ b/src/starboard/elf_loader/elf_loader.cc
@@ -35,7 +35,6 @@
           reinterpret_cast<SbAtomicPtr>(reinterpret_cast<void*>(NULL)),
           reinterpret_cast<SbAtomicPtr>(this)));
   SB_DCHECK(!old_instance);
-  SB_UNREFERENCED_PARAMETER(old_instance);
 
   impl_.reset(new ElfLoaderImpl());
 }
diff --git a/src/starboard/elf_loader/elf_loader.gyp b/src/starboard/elf_loader/elf_loader.gyp
index afb5bd6..e780c3a 100644
--- a/src/starboard/elf_loader/elf_loader.gyp
+++ b/src/starboard/elf_loader/elf_loader.gyp
@@ -90,6 +90,7 @@
       ],
       'dependencies': [
         'elf_loader',
+        '<(DEPTH)/cobalt/content/fonts/fonts.gyp:copy_font_data',
         '<(DEPTH)/starboard/starboard.gyp:starboard_full',
         # TODO: Remove this dependency once MediaSession is migrated to use CobaltExtensions.
         '<@(cobalt_platform_dependencies)',
diff --git a/src/starboard/elf_loader/elf_loader_impl.cc b/src/starboard/elf_loader/elf_loader_impl.cc
index 091b154..3bfc632 100644
--- a/src/starboard/elf_loader/elf_loader_impl.cc
+++ b/src/starboard/elf_loader/elf_loader_impl.cc
@@ -24,8 +24,7 @@
 namespace elf_loader {
 
 ElfLoaderImpl::ElfLoaderImpl() {
-#if SB_API_VERSION < 12 ||                                           \
-    !(SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) || \
+#if SB_API_VERSION < 12 || !(SB_API_VERSION >= 12 || SB_HAS(MMAP)) || \
     !SB_CAN(MAP_EXECUTABLE_MEMORY)
   SB_CHECK(false) << "The elf_loader requires SB_API_VERSION >= 12 with "
                      "executable memory map support!";
@@ -108,7 +107,7 @@
 
   if (relocations_->HasTextRelocations()) {
     // Restores the memory protection to its original state.
-#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#if SB_API_VERSION >= 12 || SB_HAS(MMAP)
     if (program_table_->AdjustMemoryProtectionOfReadOnlySegments(
             kSbMemoryMapProtectReserved) < 0) {
       SB_LOG(ERROR) << "Unable to restore segment protection";
diff --git a/src/starboard/elf_loader/elf_loader_sys_impl.cc b/src/starboard/elf_loader/elf_loader_sys_impl.cc
index 00c26c6..fd1c0a2 100644
--- a/src/starboard/elf_loader/elf_loader_sys_impl.cc
+++ b/src/starboard/elf_loader/elf_loader_sys_impl.cc
@@ -27,7 +27,6 @@
 bool ElfLoaderImpl::Load(
     const char* name,
     const void* (*custom_get_extension)(const char* name)) {
-  SB_UNREFERENCED_PARAMETER(custom_get_extension);
   SB_LOG(INFO) << "Loading: " << name;
 
   // Creating the instance forces the binary to keep all the symbols.
diff --git a/src/starboard/elf_loader/elf_loader_test.cc b/src/starboard/elf_loader/elf_loader_test.cc
index 11c31f5..303d0ff 100644
--- a/src/starboard/elf_loader/elf_loader_test.cc
+++ b/src/starboard/elf_loader/elf_loader_test.cc
@@ -17,8 +17,7 @@
 #include "starboard/common/scoped_ptr.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if SB_API_VERSION >= 12 &&                                         \
-    (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+#if SB_API_VERSION >= 12 && (SB_API_VERSION >= 12 || SB_HAS(MMAP)) && \
     SB_CAN(MAP_EXECUTABLE_MEMORY)
 namespace starboard {
 namespace elf_loader {
@@ -39,5 +38,5 @@
 }  // namespace
 }  // namespace elf_loader
 }  // namespace starboard
-#endif  // SB_API_VERSION >= 12 && (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION
+#endif  // SB_API_VERSION >= 12 && (SB_API_VERSION >= 12
         // || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/exported_symbols.cc b/src/starboard/elf_loader/exported_symbols.cc
index 492731e..49bbb9b 100644
--- a/src/starboard/elf_loader/exported_symbols.cc
+++ b/src/starboard/elf_loader/exported_symbols.cc
@@ -104,6 +104,9 @@
   REGISTER_SYMBOL(SbDrmCreateSystem);
   REGISTER_SYMBOL(SbDrmDestroySystem);
   REGISTER_SYMBOL(SbDrmGenerateSessionUpdateRequest);
+#if SB_API_VERSION >= 12
+  REGISTER_SYMBOL(SbDrmGetMetrics);
+#endif  // SB_API_VERSION >= 12
   REGISTER_SYMBOL(SbDrmUpdateSession);
   REGISTER_SYMBOL(SbEventCancel);
   REGISTER_SYMBOL(SbEventSchedule);
@@ -247,10 +250,21 @@
   REGISTER_SYMBOL(SbSystemHideSplashScreen);
   REGISTER_SYMBOL(SbSystemIsDebuggerAttached);
   REGISTER_SYMBOL(SbSystemRaisePlatformError);
+  #if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+      SB_HAS(CONCEALED_STATE)
+  REGISTER_SYMBOL(SbSystemRequestBlur);
+  REGISTER_SYMBOL(SbSystemRequestConceal);
+  REGISTER_SYMBOL(SbSystemRequestFocus);
+  REGISTER_SYMBOL(SbSystemRequestFreeze);
+  REGISTER_SYMBOL(SbSystemRequestReveal);
+  REGISTER_SYMBOL(SbSystemRequestStop);
+  #else
   REGISTER_SYMBOL(SbSystemRequestPause);
   REGISTER_SYMBOL(SbSystemRequestStop);
   REGISTER_SYMBOL(SbSystemRequestSuspend);
   REGISTER_SYMBOL(SbSystemRequestUnpause);
+  #endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+          // SB_HAS(CONCEALED_STATE)
   REGISTER_SYMBOL(SbSystemSort);
   REGISTER_SYMBOL(SbSystemSymbolize);
   REGISTER_SYMBOL(SbThreadCreate);
@@ -287,9 +301,9 @@
   REGISTER_SYMBOL(SbGetGlesInterface);
 #endif  // SB_API_VERSION >= 11
 
-#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#if SB_API_VERSION >= 12
   REGISTER_SYMBOL(SbFileAtomicReplace);
-#endif  // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #if SB_CAN(MAP_EXECUTABLE_MEMORY)
   REGISTER_SYMBOL(SbMemoryFlush);
@@ -301,18 +315,17 @@
   REGISTER_SYMBOL(SbPlayerOutputModeSupported);
 #endif
 
-#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#if SB_API_VERSION >= 12 || SB_HAS(MMAP)
   REGISTER_SYMBOL(SbMemoryMap);
   REGISTER_SYMBOL(SbMemoryUnmap);
   REGISTER_SYMBOL(SbMemoryProtect);
 #endif  // SB_HAS(MMAP)
 
-#if SB_API_VERSION >= SB_UI_NAVIGATION_VERSION
+#if SB_API_VERSION >= 12
   REGISTER_SYMBOL(SbUiNavGetInterface);
-#endif  // SB_API_VERSION >= SB_UI_NAVIGATION_VERSION
+#endif  // SB_API_VERSION >= 12
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
   REGISTER_SYMBOL(SbWindowBlurOnScreenKeyboard);
   REGISTER_SYMBOL(SbWindowFocusOnScreenKeyboard);
   REGISTER_SYMBOL(SbWindowGetOnScreenKeyboardBoundingRect);
@@ -324,19 +337,19 @@
   REGISTER_SYMBOL(SbWindowOnScreenKeyboardSuggestionsSupported);
   REGISTER_SYMBOL(SbWindowUpdateOnScreenKeyboardSuggestions);
 #endif  // SB_API_VERSION >= 11
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
   REGISTER_SYMBOL(SbWindowOnScreenKeyboardIsSupported);
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#endif  // SB_API_VERSION >= 12
 
-#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+#if SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
   REGISTER_SYMBOL(SbAccessibilityGetCaptionSettings);
   REGISTER_SYMBOL(SbAccessibilitySetCaptionsEnabled);
-#endif  // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
 
-#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE)
+#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE)
   REGISTER_SYMBOL(SbMicrophoneClose);
   REGISTER_SYMBOL(SbMicrophoneCreate);
   REGISTER_SYMBOL(SbMicrophoneDestroy);
@@ -344,46 +357,43 @@
   REGISTER_SYMBOL(SbMicrophoneIsSampleRateSupported);
   REGISTER_SYMBOL(SbMicrophoneOpen);
   REGISTER_SYMBOL(SbMicrophoneRead);
-#endif  // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(MICROPHONE)
 
-#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
   REGISTER_SYMBOL(SbSocketIsIpv6Supported);
 #endif
 
-#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_SYNTHESIS)
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_SYNTHESIS)
   REGISTER_SYMBOL(SbSpeechSynthesisCancel);
   REGISTER_SYMBOL(SbSpeechSynthesisSpeak);
-#endif  // SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_SYNTHESIS)
 
-#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION || \
-    SB_HAS(TIME_THREAD_NOW)
+#if SB_API_VERSION >= 12 || SB_HAS(TIME_THREAD_NOW)
   REGISTER_SYMBOL(SbTimeGetMonotonicThreadNow);
-#endif  // SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(TIME_THREAD_NOW)
 
 #if SB_API_VERSION >= 5
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
   REGISTER_SYMBOL(SbSpeechRecognizerIsSupported);
 #endif
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER)
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER)
   REGISTER_SYMBOL(SbSpeechRecognizerCreate);
   REGISTER_SYMBOL(SbSpeechRecognizerDestroy);
   REGISTER_SYMBOL(SbSpeechRecognizerStart);
   REGISTER_SYMBOL(SbSpeechRecognizerStop);
   REGISTER_SYMBOL(SbSpeechRecognizerCancel);
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
 #endif  // SB_API_VERSION >= 5
 
-#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
   REGISTER_SYMBOL(SbSpeechSynthesisIsSupported);
 #endif
 
-#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
   REGISTER_SYMBOL(SbTimeIsTimeThreadNowSupported);
 #endif
 
@@ -422,7 +432,7 @@
   REGISTER_SYMBOL(SbWindowGetDiagonalSizeInInches);
 #endif  // SB_API_VERSION >= 11
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
   REGISTER_SYMBOL(kSbDefaultMmapThreshold);
   REGISTER_SYMBOL(kSbFileMaxName);
   REGISTER_SYMBOL(kSbFileMaxOpen);
@@ -432,7 +442,6 @@
   REGISTER_SYMBOL(kSbFileSepChar);
   REGISTER_SYMBOL(kSbFileSepString);
   REGISTER_SYMBOL(kSbHasAc3Audio);
-  REGISTER_SYMBOL(kSbHasAsyncAudioFramesReporting);
   REGISTER_SYMBOL(kSbHasMediaWebmVp9Support);
   REGISTER_SYMBOL(kSbHasThreadPrioritySupport);
   REGISTER_SYMBOL(kSbMallocAlignment);
@@ -451,8 +460,8 @@
   REGISTER_SYMBOL(kSbPathSepString);
   REGISTER_SYMBOL(kSbPreferredRgbaByteOrder);
   REGISTER_SYMBOL(kSbUserMaxSignedIn);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-}
+#endif  // SB_API_VERSION >= 12
+}  // NOLINT
 
 const void* ExportedSymbols::Lookup(const char* name) {
   const void* address = map_[name];
diff --git a/src/starboard/elf_loader/program_table.cc b/src/starboard/elf_loader/program_table.cc
index aa1e49f..c207a92 100644
--- a/src/starboard/elf_loader/program_table.cc
+++ b/src/starboard/elf_loader/program_table.cc
@@ -75,7 +75,7 @@
 
   SB_DLOG(INFO) << "page_max - page_min=" << page_max - page_min;
 
-#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#if SB_API_VERSION >= 12 || SB_HAS(MMAP)
   phdr_mmap_ =
       SbMemoryMap(phdr_size_, kSbMemoryMapProtectWrite, "program_header");
   if (!phdr_mmap_) {
@@ -93,7 +93,7 @@
                   << page_min;
     return false;
   }
-#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#if SB_API_VERSION >= 12 || SB_HAS(MMAP)
   bool mp_result =
       SbMemoryProtect(phdr_mmap_, phdr_size_, kSbMemoryMapProtectRead);
   SB_DLOG(INFO) << "mp_result=" << mp_result;
@@ -143,8 +143,7 @@
                   << " file_length=" << file_length << " seg_page_start=0x"
                   << std::hex << seg_page_start;
 
-#if (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
-    SB_CAN(MAP_EXECUTABLE_MEMORY)
+#if (SB_API_VERSION >= 12 || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
     if (file_length != 0) {
       const int prot_flags = PFLAGS_TO_PROT(phdr->p_flags);
       SB_DLOG(INFO) << "segment prot_flags=" << std::hex << prot_flags;
@@ -194,8 +193,7 @@
     // between them. This is done by using a private anonymous
     // map for all extra pages.
     if (seg_page_end > seg_file_end) {
-#if (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
-    SB_CAN(MAP_EXECUTABLE_MEMORY)
+#if (SB_API_VERSION >= 12 || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
       bool mprotect_fix = SbMemoryProtect(reinterpret_cast<void*>(seg_file_end),
                                           seg_page_end - seg_file_end,
                                           kSbMemoryMapProtectWrite);
@@ -210,8 +208,7 @@
 
       SbMemorySet(reinterpret_cast<void*>(seg_file_end), 0,
                   seg_page_end - seg_file_end);
-#if (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
-    SB_CAN(MAP_EXECUTABLE_MEMORY)
+#if (SB_API_VERSION >= 12 || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
       SbMemoryProtect(reinterpret_cast<void*>(seg_file_end),
                       seg_page_end - seg_file_end,
                       PFLAGS_TO_PROT(phdr->p_flags));
@@ -305,8 +302,7 @@
     Addr seg_page_start = PAGE_START(phdr->p_vaddr) + base_memory_address_;
     Addr seg_page_end =
         PAGE_END(phdr->p_vaddr + phdr->p_memsz) + base_memory_address_;
-#if (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
-    SB_CAN(MAP_EXECUTABLE_MEMORY)
+#if (SB_API_VERSION >= 12 || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
     int ret = SbMemoryProtect(reinterpret_cast<void*>(seg_page_start),
                               seg_page_end - seg_page_start,
                               PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags);
@@ -329,7 +325,7 @@
 
   SB_DLOG(INFO) << "Load size=" << load_size_;
 
-#if (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP))
+#if (SB_API_VERSION >= 12 || SB_HAS(MMAP))
   load_start_ =
       SbMemoryMap(load_size_, kSbMemoryMapProtectReserved, "reserved_mem");
   if (load_start_ == MAP_FAILED) {
@@ -364,7 +360,7 @@
 
 ProgramTable::~ProgramTable() {
   SetEvergreenInfo(NULL);
-#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#if SB_API_VERSION >= 12 || SB_HAS(MMAP)
   if (load_start_) {
     SbMemoryUnmap(load_start_, load_size_);
   }
diff --git a/src/starboard/elf_loader/program_table_test.cc b/src/starboard/elf_loader/program_table_test.cc
index b2b6efa..e1716f3 100644
--- a/src/starboard/elf_loader/program_table_test.cc
+++ b/src/starboard/elf_loader/program_table_test.cc
@@ -21,8 +21,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if SB_API_VERSION >= 12 &&                                         \
-    (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+#if SB_API_VERSION >= 12 && (SB_API_VERSION >= 12 || SB_HAS(MMAP)) && \
     SB_CAN(MAP_EXECUTABLE_MEMORY)
 namespace starboard {
 namespace elf_loader {
@@ -184,5 +183,5 @@
 }  // namespace
 }  // namespace elf_loader
 }  // namespace starboard
-#endif  // SB_API_VERSION >= 12 && (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION
+#endif  // SB_API_VERSION >= 12 && (SB_API_VERSION >= 12
         // || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/relocations_test.cc b/src/starboard/elf_loader/relocations_test.cc
index 1bb2b7b..20010e5 100644
--- a/src/starboard/elf_loader/relocations_test.cc
+++ b/src/starboard/elf_loader/relocations_test.cc
@@ -20,8 +20,7 @@
 #include "starboard/string.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if SB_API_VERSION >= 12 &&                                         \
-    (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+#if SB_API_VERSION >= 12 && (SB_API_VERSION >= 12 || SB_HAS(MMAP)) && \
     SB_CAN(MAP_EXECUTABLE_MEMORY)
 namespace starboard {
 namespace elf_loader {
@@ -384,5 +383,5 @@
 }  // namespace
 }  // namespace elf_loader
 }  // namespace starboard
-#endif  // SB_API_VERSION >= 12 && (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION
+#endif  // SB_API_VERSION >= 12 && (SB_API_VERSION >= 12
         // || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/event.h b/src/starboard/event.h
index 8fea369..feca155 100644
--- a/src/starboard/event.h
+++ b/src/starboard/event.h
@@ -12,6 +12,85 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// For platforms that define SB_HAS_CONCEALED_STATE
+//
+// Module Overview: Starboard Event module
+//
+// Defines the event system that wraps the Starboard main loop and entry point.
+//
+// # The Starboard Application Lifecycle
+//
+//                    * ----------
+//                    |           |
+//                  Start         |
+//                    |           |
+//                    V           |
+//              [===========]     |
+//         ---> [  STARTED  ]     |
+//        |     [===========]     |
+//        |           |           |
+//      Focus       Blur      Preload
+//        |           |           |
+//        |           V           |
+//         ---- [===========]     |
+//         ---> [  BLURRED  ]     |
+//        |     [===========]     |
+//        |           |           |
+//      Reveal     Conceal        |
+//        |           |           |
+//        |           V           |
+//        |     [===========]     |
+//         ---- [ CONCEALED ] <---
+//         ---> [===========]
+//        |           |
+//     Unfreeze     Freeze
+//        |           |
+//        |           V
+//        |     [===========]
+//         ---- [  FROZEN   ]
+//              [===========]
+//                    |
+//                   Stop
+//                    |
+//                    V
+//              [===========]
+//              [  STOPPED  ]
+//              [===========]
+//
+// The first event that a Starboard application receives is either |Start|
+// (|kSbEventTypeStart|) or |Preload| (|kSbEventTypePreload|). |Start| puts the
+// application in the |STARTED| state, whereas |Preload| puts the application in
+// the |CONCEALED| state.
+//
+// In the |STARTED| state, the application is in the foreground and can expect
+// to do all of the normal things it might want to do. Once in the |STARTED|
+// state, it may receive a |Blur| event, putting the application into the
+// |BLURRED| state.
+//
+// In the |BLURRED| state, the application is still visible, but has lost
+// focus, or it is partially obscured by a modal dialog, or it is on its way
+// to being shut down. The application should blur activity in this state.
+// In this state, it can receive |Focus| to be brought back to the foreground
+// state (|STARTED|), or |Conceal| to be pushed to the |CONCEALED| state.
+//
+// In the |CONCEALED| state, the application should behave as it should for
+// an invisible program that can still run, and that can optionally access
+// the network and playback audio, albeit potentially will have less
+// CPU and memory available. The application may get switched from |CONCEALED|
+// to |FROZEN| at any time, when the platform decides to do so.
+//
+// In the |FROZEN| state, the application is not visible. It should immediately
+// release all graphics and video resources, and shut down all background
+// activity (timers, rendering, etc). Additionally, the application should
+// flush storage to ensure that if the application is killed, the storage will
+// be up-to-date. The application may be killed at this point, but will ideally
+// receive a |Stop| event for a more graceful shutdown.
+//
+// Note that the application is always expected to transition through |BLURRED|,
+// |CONCEALED| to |FROZEN| before receiving |Stop| or being killed.
+//
+// For platforms that do not define SB_HAS_CONCEALED_STATE
+//
 // Module Overview: Starboard Event module
 //
 // Defines the event system that wraps the Starboard main loop and entry point.
@@ -97,6 +176,81 @@
 // system. Each event is accompanied by a void* data argument, and each event
 // must define the type of the value pointed to by that data argument, if any.
 typedef enum SbEventType {
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+  // Applications should perform initialization and prepare to react to
+  // subsequent events, but must not initialize any graphics resources (through
+  // GL or SbBlitter). The intent of this event is to allow the application to
+  // do as much work as possible ahead of time, so that when the application is
+  // first brought to the foreground, it's as fast as a resume.
+
+  // The system may send |kSbEventTypePreload| in |UNSTARTED| if it wants to
+  // push the app into a lower resource consumption state. Applications will
+  // also call SbSystemRequestConceal() when they request this. The only
+  // events that should be dispatched after a Preload event are Reveal or
+  // Freeze. No data argument.
+  kSbEventTypePreload,
+
+  // The first event that an application receives on startup when starting
+  // normally. Applications should perform initialization, start running,
+  // and prepare to react to subsequent events. Applications that wish to run
+  // and then exit must call |SbSystemRequestStop()| to terminate. This event
+  // will only be sent once for a given process launch. |SbEventStartData| is
+  // passed as the data argument.
+  kSbEventTypeStart,
+
+  // A dialog will be raised or the application will otherwise be put into a
+  // background-but-visible or partially-obscured state (BLURRED). Graphics and
+  // video resources will still be available, but the application could pause
+  // foreground activity like animations and video playback. Can only be
+  // received after a Start event. The only events that should be dispatched
+  // after a Blur event are Focus or Conceal. No data argument.
+  kSbEventTypeBlur,
+
+  // The application is returning to the foreground (STARTED) after having been
+  // put in the BLURRED (e.g. partially-obscured) state. The application should
+  // resume foreground activity like animations and video playback. Can only be
+  // received after a Blur or Reveal event. No data argument.
+  kSbEventTypeFocus,
+
+  // The operating system will put the application into the Concealed state
+  // after this event is handled. The application is expected to be made
+  // invisible, but background tasks can still be running, such as audio
+  // playback, or updating of recommandations. Can only be received after a
+  // Blur or Reveal event. The only events that should be dispatched after
+  // a Conceal event are Freeze or Reveal. On some platforms, the process may
+  // also be killed after Conceal without a Freeze event.
+  kSbEventTypeConceal,
+
+  // The operating system will restore the application to the BLURRED state
+  // from the CONCEALED state. This is the first event the application will
+  // receive coming out of CONCEALED, and it can be received after a
+  // Conceal or Unfreeze event. The application will now be in the BLURRED
+  // state. No data argument.
+  kSbEventTypeReveal,
+
+  // The operating system will put the application into the Frozen state after
+  // this event is handled. The application is expected to stop periodic
+  // background work, release ALL graphics and video resources, and flush any
+  // pending SbStorage writes. Some platforms will terminate the application if
+  // work is done or resources are retained after freezing. Can be received
+  // after a Conceal or Unfreeze event. The only events that should be
+  // dispatched after a Freeze event are Unfreeze or Stop. On some platforms,
+  // the process may also be killed after Freeze without a Stop event.
+  // No data argument.
+  kSbEventTypeFreeze,
+
+  // The operating system has restored the application to the CONCEALED state
+  // from the FROZEN state. This is the first event the application will receive
+  // coming out of FROZEN, and it will only be received after a Freeze event.
+  // The application will now be in the CONCEALED state. NO data argument.
+  kSbEventTypeUnfreeze,
+
+  // The operating system will shut the application down entirely after this
+  // event is handled. Can only be received after a Freeze event, in the
+  // FROZEN state. No data argument.
+  kSbEventTypeStop,
+# else
   // Applications should perform initialization and prepare to react to
   // subsequent events, but must not initialize any graphics resources (through
   // GL or SbBlitter). The intent of this event is to allow the application to
@@ -137,7 +291,6 @@
   // unpause foreground activity like animations and video playback. Can only be
   // received after a Pause or Resume event. No data argument.
   kSbEventTypeUnpause,
-
   // The operating system will put the application into a Suspended state after
   // this event is handled. The application is expected to stop periodic
   // background work, release ALL graphics and video resources, and flush any
@@ -155,9 +308,11 @@
   kSbEventTypeResume,
 
   // The operating system will shut the application down entirely after this
-  // event is handled. Can only be recieved after a Suspend event, in the
+  // event is handled. Can only be received after a Suspend event, in the
   // SUSPENDED state. No data argument.
   kSbEventTypeStop,
+  #endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
 
   // A user input event, including keyboard, mouse, gesture, or something else.
   // SbInputData (from input.h) is passed as the data argument.
@@ -219,8 +374,7 @@
   // SbEventWindowSizeChangedData.
   kSbEventTypeWindowSizeChanged,
 #endif  // SB_API_VERSION >= 8
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
   // The platform has shown the on screen keyboard. This event is triggered by
   // the system or by the application's OnScreenKeyboard show method. The event
   // has int data representing a ticket. The ticket is used by the application
@@ -269,13 +423,13 @@
   kSbEventTypeOnScreenKeyboardSuggestionsUpdated,
 #endif  // SB_API_VERSION >= 11
 
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
-#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+#if SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
   // One or more of the fields returned by SbAccessibilityGetCaptionSettings
   // has changed.
   kSbEventTypeAccessibilityCaptionSettingsChanged,
-#endif  // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
 } SbEventType;
 
 // Structure representing a Starboard event and its data.
diff --git a/src/starboard/evergreen/arm/hardfp/configuration_public.h b/src/starboard/evergreen/arm/hardfp/configuration_public.h
index b813c19..cdeafc9 100644
--- a/src/starboard/evergreen/arm/hardfp/configuration_public.h
+++ b/src/starboard/evergreen/arm/hardfp/configuration_public.h
@@ -163,7 +163,7 @@
 
 // Whether this platform has and should use an MMAP function to map physical
 // memory to the virtual address space.
-#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#if SB_API_VERSION < 12
 #define SB_HAS_MMAP 1
 #endif
 
diff --git a/src/starboard/evergreen/arm/hardfp/gyp_configuration.py b/src/starboard/evergreen/arm/hardfp/gyp_configuration.py
index 467ce05..db3e2cb 100644
--- a/src/starboard/evergreen/arm/hardfp/gyp_configuration.py
+++ b/src/starboard/evergreen/arm/hardfp/gyp_configuration.py
@@ -22,4 +22,4 @@
 def CreatePlatformConfig():
   return parent_configuration.EvergreenArmConfiguration(
       'evergreen-arm-hardfp',
-      sabi_json_path='starboard/sabi/arm/hardfp/sabi.json')
+      sabi_json_path='starboard/sabi/arm/hardfp/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/evergreen/arm/hardfp/sbversion/12/atomic_public.h
similarity index 63%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/evergreen/arm/hardfp/sbversion/12/atomic_public.h
index 0fbc0ef..7f66416 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/evergreen/arm/hardfp/sbversion/12/atomic_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM_HARDFP_SBVERSION_12_ATOMIC_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_HARDFP_SBVERSION_12_ATOMIC_PUBLIC_H_
 
-#include "starboard/raspi/shared/atomic_public.h"
+#include "starboard/evergreen/arm/hardfp/atomic_public.h"
 
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#endif  // STARBOARD_EVERGREEN_ARM_HARDFP_SBVERSION_12_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/raspi/0/configuration_public.h b/src/starboard/evergreen/arm/hardfp/sbversion/12/configuration_public.h
similarity index 60%
copy from src/starboard/raspi/0/configuration_public.h
copy to src/starboard/evergreen/arm/hardfp/sbversion/12/configuration_public.h
index d2c292b..4be69b0 100644
--- a/src/starboard/raspi/0/configuration_public.h
+++ b/src/starboard/evergreen/arm/hardfp/sbversion/12/configuration_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,14 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// The Starboard configuration for Raspberry PI 1 Raspbian.
+// The Starboard configuration for X86_64. Other devices will have
+// specific Starboard implementations.
 
 // Other source files should never include this header directly, but should
 // include the generic "starboard/configuration.h" instead.
 
-#ifndef STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM_HARDFP_SBVERSION_12_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_HARDFP_SBVERSION_12_CONFIGURATION_PUBLIC_H_
 
-#include "starboard/raspi/shared/configuration_public.h"
+#include "starboard/evergreen/arm/hardfp/configuration_public.h"
 
-#endif  // STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
+#endif  // STARBOARD_EVERGREEN_ARM_HARDFP_SBVERSION_12_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/evergreen/arm/hardfp/sbversion/12/gyp_configuration.gypi b/src/starboard/evergreen/arm/hardfp/sbversion/12/gyp_configuration.gypi
new file mode 100644
index 0000000..0c67bd5
--- /dev/null
+++ b/src/starboard/evergreen/arm/hardfp/sbversion/12/gyp_configuration.gypi
@@ -0,0 +1,42 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+  'variables': {
+    'sb_target_platform': 'evergreen-arm-hardfp',
+  },
+  'target_defaults': {
+    'default_configuration': 'evergreen-arm-hardfp-sbversion-12_debug',
+    'configurations': {
+      'evergreen-arm-hardfp-sbversion-12_debug': {
+        'inherit_from': ['debug_base'],
+      },
+      'evergreen-arm-hardfp-sbversion-12_devel': {
+        'inherit_from': ['devel_base'],
+      },
+      'evergreen-arm-hardfp-sbversion-12_qa': {
+        'inherit_from': ['qa_base'],
+      },
+      'evergreen-arm-hardfp-sbversion-12_gold': {
+        'inherit_from': ['gold_base'],
+      },
+    }, # end of configurations
+  },
+  'includes': [
+    '<(DEPTH)/starboard/evergreen/arm/shared/gyp_configuration.gypi',
+  ],
+}
diff --git a/src/starboard/evergreen/arm/hardfp/sbversion/12/gyp_configuration.py b/src/starboard/evergreen/arm/hardfp/sbversion/12/gyp_configuration.py
new file mode 100644
index 0000000..6097401
--- /dev/null
+++ b/src/starboard/evergreen/arm/hardfp/sbversion/12/gyp_configuration.py
@@ -0,0 +1,25 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+"""Starboard evergreen-arm-hardfp platform configuration for gyp_cobalt."""
+
+from starboard.evergreen.arm.shared import gyp_configuration as parent_configuration
+
+
+def CreatePlatformConfig():
+  return parent_configuration.EvergreenArmConfiguration(
+      'evergreen-arm-hardfp-sbversion-12',
+      sabi_json_path='starboard/sabi/arm/hardfp/sabi-v12.json')
diff --git a/src/starboard/evergreen/arm/hardfp/sbversion/12/starboard_platform.gyp b/src/starboard/evergreen/arm/hardfp/sbversion/12/starboard_platform.gyp
new file mode 100644
index 0000000..29566d2
--- /dev/null
+++ b/src/starboard/evergreen/arm/hardfp/sbversion/12/starboard_platform.gyp
@@ -0,0 +1,25 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+  'includes': [
+    # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file.  The idea
+    # is that we just want this file to *be* the parent gyp file.
+    '<(DEPTH)/starboard/evergreen/arm/hardfp/starboard_platform.gyp',
+  ],
+}
+
diff --git a/src/starboard/evergreen/arm/hardfp/sbversion/12/thread_types_public.h b/src/starboard/evergreen/arm/hardfp/sbversion/12/thread_types_public.h
new file mode 100644
index 0000000..903d6bd
--- /dev/null
+++ b/src/starboard/evergreen/arm/hardfp/sbversion/12/thread_types_public.h
@@ -0,0 +1,23 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file was initially generated by starboard/tools/create_derived_build.py,
+// though it may have been modified since its creation.
+
+#ifndef STARBOARD_EVERGREEN_ARM_HARDFP_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_HARDFP_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+
+#include "starboard/evergreen/arm/hardfp/thread_types_public.h"
+
+#endif  // STARBOARD_EVERGREEN_ARM_HARDFP_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/evergreen/arm/shared/gyp_configuration.py b/src/starboard/evergreen/arm/shared/gyp_configuration.py
index d442333..c6c67ed 100644
--- a/src/starboard/evergreen/arm/shared/gyp_configuration.py
+++ b/src/starboard/evergreen/arm/shared/gyp_configuration.py
@@ -35,7 +35,7 @@
                platform_name='evergreen-arm',
                asan_enabled_by_default=False,
                goma_supports_compiler=True,
-               sabi_json_path=None):
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     # pylint: disable=useless-super-delegation
     super(EvergreenArmConfiguration,
           self).__init__(platform_name, asan_enabled_by_default,
@@ -43,10 +43,10 @@
     self.AppendApplicationConfigurationPath(os.path.dirname(__file__))
     self._host_toolchain = None
 
-  def GetTargetToolchain(self):
-    return self.GetHostToolchain()
+  def GetTargetToolchain(self, **kwargs):
+    return self.GetHostToolchain(**kwargs)
 
-  def GetHostToolchain(self):
+  def GetHostToolchain(self, **kwargs):
     if not self._host_toolchain:
       if not hasattr(self, 'host_compiler_environment'):
         self.host_compiler_environment = build.GetHostCompilerEnvironment(
@@ -84,7 +84,8 @@
     return filters
 
   def GetVariables(self, configuration):
-    variables = super(EvergreenArmConfiguration, self).GetVariables(configuration)
+    variables = super(EvergreenArmConfiguration,
+                      self).GetVariables(configuration)
     variables.update({
         'include_path_platform_deploy_gypi':
             'starboard/evergreen/arm/shared/platform_deploy.gypi',
diff --git a/src/starboard/evergreen/arm/softfp/configuration_public.h b/src/starboard/evergreen/arm/softfp/configuration_public.h
index 1743bba..b6ced7d 100644
--- a/src/starboard/evergreen/arm/softfp/configuration_public.h
+++ b/src/starboard/evergreen/arm/softfp/configuration_public.h
@@ -166,7 +166,7 @@
 
 // Whether this platform has and should use an MMAP function to map physical
 // memory to the virtual address space.
-#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#if SB_API_VERSION < 12
 #define SB_HAS_MMAP 1
 #endif
 
diff --git a/src/starboard/evergreen/arm/softfp/gyp_configuration.py b/src/starboard/evergreen/arm/softfp/gyp_configuration.py
index 8c649b9..46418c1 100644
--- a/src/starboard/evergreen/arm/softfp/gyp_configuration.py
+++ b/src/starboard/evergreen/arm/softfp/gyp_configuration.py
@@ -22,4 +22,4 @@
 def CreatePlatformConfig():
   return parent_configuration.EvergreenArmConfiguration(
       'evergreen-arm-softfp',
-      sabi_json_path='starboard/sabi/arm/softfp/sabi.json')
+      sabi_json_path='starboard/sabi/arm/softfp/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/evergreen/arm/softfp/sbversion/12/atomic_public.h
similarity index 63%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/evergreen/arm/softfp/sbversion/12/atomic_public.h
index 0fbc0ef..d11da25 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/evergreen/arm/softfp/sbversion/12/atomic_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM_SOFTFP_SBVERSION_12_ATOMIC_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_SOFTFP_SBVERSION_12_ATOMIC_PUBLIC_H_
 
-#include "starboard/raspi/shared/atomic_public.h"
+#include "starboard/evergreen/arm/softfp/atomic_public.h"
 
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#endif  // STARBOARD_EVERGREEN_ARM_SOFTFP_SBVERSION_12_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/raspi/0/configuration_public.h b/src/starboard/evergreen/arm/softfp/sbversion/12/configuration_public.h
similarity index 60%
copy from src/starboard/raspi/0/configuration_public.h
copy to src/starboard/evergreen/arm/softfp/sbversion/12/configuration_public.h
index d2c292b..e4f45f4 100644
--- a/src/starboard/raspi/0/configuration_public.h
+++ b/src/starboard/evergreen/arm/softfp/sbversion/12/configuration_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,14 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// The Starboard configuration for Raspberry PI 1 Raspbian.
+// The Starboard configuration for X86_64. Other devices will have
+// specific Starboard implementations.
 
 // Other source files should never include this header directly, but should
 // include the generic "starboard/configuration.h" instead.
 
-#ifndef STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM_SOFTFP_SBVERSION_12_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_SOFTFP_SBVERSION_12_CONFIGURATION_PUBLIC_H_
 
-#include "starboard/raspi/shared/configuration_public.h"
+#include "starboard/evergreen/arm/softfp/configuration_public.h"
 
-#endif  // STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
+#endif  // STARBOARD_EVERGREEN_ARM_SOFTFP_SBVERSION_12_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/evergreen/arm/softfp/sbversion/12/gyp_configuration.gypi b/src/starboard/evergreen/arm/softfp/sbversion/12/gyp_configuration.gypi
new file mode 100644
index 0000000..d31f2b7
--- /dev/null
+++ b/src/starboard/evergreen/arm/softfp/sbversion/12/gyp_configuration.gypi
@@ -0,0 +1,42 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+  'variables': {
+    'sb_target_platform': 'evergreen-arm-softfp',
+  },
+  'target_defaults': {
+    'default_configuration': 'evergreen-arm-softfp-sbversion-12_debug',
+    'configurations': {
+      'evergreen-arm-softfp-sbversion-12_debug': {
+        'inherit_from': ['debug_base'],
+      },
+      'evergreen-arm-softfp-sbversion-12_devel': {
+        'inherit_from': ['devel_base'],
+      },
+      'evergreen-arm-softfp-sbversion-12_qa': {
+        'inherit_from': ['qa_base'],
+      },
+      'evergreen-arm-softfp-sbversion-12_gold': {
+        'inherit_from': ['gold_base'],
+      },
+    }, # end of configurations
+  },
+  'includes': [
+    '<(DEPTH)/starboard/evergreen/arm/shared/gyp_configuration.gypi',
+  ],
+}
diff --git a/src/starboard/evergreen/arm/softfp/sbversion/12/gyp_configuration.py b/src/starboard/evergreen/arm/softfp/sbversion/12/gyp_configuration.py
new file mode 100644
index 0000000..f5d1aff
--- /dev/null
+++ b/src/starboard/evergreen/arm/softfp/sbversion/12/gyp_configuration.py
@@ -0,0 +1,25 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+"""Starboard evergreen-arm-softfp platform configuration for gyp_cobalt."""
+
+from starboard.evergreen.arm.shared import gyp_configuration as parent_configuration
+
+
+def CreatePlatformConfig():
+  return parent_configuration.EvergreenArmConfiguration(
+      'evergreen-arm-softfp-sbversion-12',
+      sabi_json_path='starboard/sabi/arm/softfp/sabi-v12.json')
diff --git a/src/starboard/evergreen/arm/softfp/sbversion/12/starboard_platform.gyp b/src/starboard/evergreen/arm/softfp/sbversion/12/starboard_platform.gyp
new file mode 100644
index 0000000..b4aa959
--- /dev/null
+++ b/src/starboard/evergreen/arm/softfp/sbversion/12/starboard_platform.gyp
@@ -0,0 +1,25 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+  'includes': [
+    # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file.  The idea
+    # is that we just want this file to *be* the parent gyp file.
+    '<(DEPTH)/starboard/evergreen/arm/softfp/starboard_platform.gyp',
+  ],
+}
+
diff --git a/src/starboard/evergreen/arm/softfp/sbversion/12/thread_types_public.h b/src/starboard/evergreen/arm/softfp/sbversion/12/thread_types_public.h
new file mode 100644
index 0000000..ac72552
--- /dev/null
+++ b/src/starboard/evergreen/arm/softfp/sbversion/12/thread_types_public.h
@@ -0,0 +1,23 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file was initially generated by starboard/tools/create_derived_build.py,
+// though it may have been modified since its creation.
+
+#ifndef STARBOARD_EVERGREEN_ARM_SOFTFP_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_SOFTFP_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+
+#include "starboard/evergreen/arm/softfp/thread_types_public.h"
+
+#endif  // STARBOARD_EVERGREEN_ARM_SOFTFP_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/evergreen/arm64/configuration_public.h b/src/starboard/evergreen/arm64/configuration_public.h
index 9d5aac5..73939b3 100644
--- a/src/starboard/evergreen/arm64/configuration_public.h
+++ b/src/starboard/evergreen/arm64/configuration_public.h
@@ -182,7 +182,7 @@
 
 // Whether this platform has and should use an MMAP function to map physical
 // memory to the virtual address space.
-#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#if SB_API_VERSION < 12
 #define SB_HAS_MMAP 1
 #endif
 
diff --git a/src/starboard/evergreen/arm64/gyp_configuration.py b/src/starboard/evergreen/arm64/gyp_configuration.py
index a607170..fc09a0d 100644
--- a/src/starboard/evergreen/arm64/gyp_configuration.py
+++ b/src/starboard/evergreen/arm64/gyp_configuration.py
@@ -32,17 +32,17 @@
                platform_name='evergreen-arm64',
                asan_enabled_by_default=False,
                goma_supports_compiler=True,
-               sabi_json_path=None):
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     # pylint: disable=useless-super-delegation
     super(EvergreenArm64Configuration,
           self).__init__(platform_name, asan_enabled_by_default,
                          goma_supports_compiler, sabi_json_path)
     self._host_toolchain = None
 
-  def GetTargetToolchain(self):
-    return self.GetHostToolchain()
+  def GetTargetToolchain(self, **kwargs):
+    return self.GetHostToolchain(**kwargs)
 
-  def GetHostToolchain(self):
+  def GetHostToolchain(self, **kwargs):
     if not self._host_toolchain:
       if not hasattr(self, 'host_compiler_environment'):
         self.host_compiler_environment = build.GetHostCompilerEnvironment(
@@ -78,7 +78,8 @@
     return super(EvergreenArm64Configuration, self).GetTestFilters()
 
   def GetVariables(self, configuration):
-    variables = super(EvergreenArm64Configuration, self).GetVariables(configuration)
+    variables = super(EvergreenArm64Configuration,
+                      self).GetVariables(configuration)
     variables.update({
         'include_path_platform_deploy_gypi':
             'starboard/evergreen/arm64/platform_deploy.gypi',
@@ -88,4 +89,4 @@
 
 def CreatePlatformConfig():
   return EvergreenArm64Configuration(
-      sabi_json_path='starboard/sabi/arm64/sabi.json')
+      sabi_json_path='starboard/sabi/arm64/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/evergreen/arm64/sbversion/12/atomic_public.h
similarity index 64%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/evergreen/arm64/sbversion/12/atomic_public.h
index 0fbc0ef..2604b7e 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/evergreen/arm64/sbversion/12/atomic_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM64_SBVERSION_12_ATOMIC_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM64_SBVERSION_12_ATOMIC_PUBLIC_H_
 
-#include "starboard/raspi/shared/atomic_public.h"
+#include "starboard/evergreen/arm64/atomic_public.h"
 
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#endif  // STARBOARD_EVERGREEN_ARM64_SBVERSION_12_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/raspi/0/configuration_public.h b/src/starboard/evergreen/arm64/sbversion/12/configuration_public.h
similarity index 61%
copy from src/starboard/raspi/0/configuration_public.h
copy to src/starboard/evergreen/arm64/sbversion/12/configuration_public.h
index d2c292b..4ff33d9 100644
--- a/src/starboard/raspi/0/configuration_public.h
+++ b/src/starboard/evergreen/arm64/sbversion/12/configuration_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,14 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// The Starboard configuration for Raspberry PI 1 Raspbian.
+// The Starboard configuration for X86_64. Other devices will have
+// specific Starboard implementations.
 
 // Other source files should never include this header directly, but should
 // include the generic "starboard/configuration.h" instead.
 
-#ifndef STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM64_SBVERSION_12_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM64_SBVERSION_12_CONFIGURATION_PUBLIC_H_
 
-#include "starboard/raspi/shared/configuration_public.h"
+#include "starboard/evergreen/arm64/configuration_public.h"
 
-#endif  // STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
+#endif  // STARBOARD_EVERGREEN_ARM64_SBVERSION_12_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/evergreen/arm64/sbversion/12/gyp_configuration.gypi b/src/starboard/evergreen/arm64/sbversion/12/gyp_configuration.gypi
new file mode 100644
index 0000000..5460de1
--- /dev/null
+++ b/src/starboard/evergreen/arm64/sbversion/12/gyp_configuration.gypi
@@ -0,0 +1,58 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+  'variables': {
+    'yasm_exists': 1,
+    'sb_target_platform': 'evergreen-arm64',
+
+    'compiler_flags': [
+      '-isystem<(cobalt_repo_root)/third_party/musl/arch/aarch64',
+    ],
+  },
+
+  'target_defaults': {
+    'defines' : [
+      # Ensure that the Starboardized __external_threading file is included.
+      '_LIBCPP_HAS_THREAD_API_EXTERNAL',
+      # Ensure that only the forward declarations and type definitions are included
+      # in __external_threading.
+      '_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL',
+      # Enable GNU extensions to get prototypes like ffsl.
+      '_GNU_SOURCE=1',
+    ],
+    'default_configuration': 'evergreen-arm64-sbversion-12_debug',
+    'configurations': {
+      'evergreen-arm64-sbversion-12_debug': {
+        'inherit_from': ['debug_base'],
+      },
+      'evergreen-arm64-sbversion-12_devel': {
+        'inherit_from': ['devel_base'],
+      },
+      'evergreen-arm64-sbversion-12_qa': {
+        'inherit_from': ['qa_base'],
+      },
+      'evergreen-arm64-sbversion-12_gold': {
+        'inherit_from': ['gold_base'],
+      },
+    }, # end of configurations
+  },
+  'includes': [
+    '<(DEPTH)/starboard/evergreen/shared/compiler_flags.gypi',
+    '<(DEPTH)/starboard/evergreen/shared/gyp_configuration.gypi',
+  ],
+}
diff --git a/src/starboard/evergreen/arm64/sbversion/12/gyp_configuration.py b/src/starboard/evergreen/arm64/sbversion/12/gyp_configuration.py
new file mode 100644
index 0000000..f0b21ba
--- /dev/null
+++ b/src/starboard/evergreen/arm64/sbversion/12/gyp_configuration.py
@@ -0,0 +1,22 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Starboard evergreen-arm64 platform configuration for gyp_cobalt."""
+
+from starboard.evergreen.arm64 import gyp_configuration as parent_configuration
+
+
+def CreatePlatformConfig():
+  return parent_configuration.EvergreenArm64Configuration(
+      platform_name='evergreen-arm64-sbversion-12',
+      sabi_json_path='starboard/sabi/arm64/sabi-v12.json')
diff --git a/src/starboard/raspi/0/starboard_platform.gyp b/src/starboard/evergreen/arm64/sbversion/12/starboard_platform.gyp
similarity index 67%
copy from src/starboard/raspi/0/starboard_platform.gyp
copy to src/starboard/evergreen/arm64/sbversion/12/starboard_platform.gyp
index 021af7c..6b4361f 100644
--- a/src/starboard/raspi/0/starboard_platform.gyp
+++ b/src/starboard/evergreen/arm64/sbversion/12/starboard_platform.gyp
@@ -1,4 +1,4 @@
-# Copyright 2017 The Cobalt Authors. All Rights Reserved.
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -11,8 +11,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 {
   'includes': [
-    '../shared/starboard_platform.gypi',
+    # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file.  The idea
+    # is that we just want this file to *be* the parent gyp file.
+    '<(DEPTH)/starboard/evergreen/arm64/starboard_platform.gyp',
   ],
 }
diff --git a/src/starboard/evergreen/arm64/sbversion/12/thread_types_public.h b/src/starboard/evergreen/arm64/sbversion/12/thread_types_public.h
new file mode 100644
index 0000000..14e88b4
--- /dev/null
+++ b/src/starboard/evergreen/arm64/sbversion/12/thread_types_public.h
@@ -0,0 +1,23 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file was initially generated by starboard/tools/create_derived_build.py,
+// though it may have been modified since its creation.
+
+#ifndef STARBOARD_EVERGREEN_ARM64_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM64_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+
+#include "starboard/evergreen/arm64/thread_types_public.h"
+
+#endif  // STARBOARD_EVERGREEN_ARM64_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/evergreen/sabi/sbversion/12/sabi_flags.gypi b/src/starboard/evergreen/sabi/sbversion/12/sabi_flags.gypi
new file mode 100644
index 0000000..160ef7f
--- /dev/null
+++ b/src/starboard/evergreen/sabi/sbversion/12/sabi_flags.gypi
@@ -0,0 +1,80 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Starboard Application Binary Interface
+#
+# This file translates the set of ABI variables, which should be overridden by
+# each platform, into platform-specific sets of compiler flags.
+
+{
+  'variables': {
+    'conditions': [
+      # arm
+      ['target_arch=="arm"', {
+        'compiler_flags': [
+          '-march=arm<(target_arch_sub)',
+        ],
+        'conditions': [
+          ['floating_point_abi=="soft"', {
+            'compiler_flags': [
+              '-mfloat-abi=soft',
+            ],
+          }, {
+            'compiler_flags': [
+              '-mfloat-abi=<(floating_point_abi)',
+              '-mfpu=<(floating_point_fpu)',
+            ],
+          }],
+          ['floating_point_abi=="hard"', {
+            'compiler_flags': [
+              '-target', 'arm<(target_arch_sub)-none-eabihf',
+            ],
+          }, {
+            'compiler_flags': [
+              '-target', 'arm<(target_arch_sub)-none-eabi',
+            ],
+          }],
+        ],
+      }],
+      # arm64
+      ['target_arch=="arm64"', {
+        'compiler_flags': [
+          '-march=arm64<(target_arch_sub)',
+          '-target', 'arm64<(target_arch_sub)-unknown-unknown-elf',
+
+          # There is no software floating point support for arm64 / aarch64
+          # architectures. Thus, -mfloat-abi and -mfpu would simply be ignored.
+
+          # char is unsigned by default for arm64.
+          '-fsigned-char',
+        ],
+      }],
+      # x86
+      ['target_arch=="x86"', {
+        'compiler_flags': [
+          '-march=i686',
+          '-target', 'i686-unknown-unknown-elf',
+        ],
+      }],
+      # x64
+      ['target_arch=="x64"', {
+        'compiler_flags': [
+          '-march=x86-64',
+          '-target', 'x86_64-unknown-linux-elf',
+        ],
+      }],
+    ],
+  },
+}
+
diff --git a/src/starboard/evergreen/shared/gyp_configuration.gypi b/src/starboard/evergreen/shared/gyp_configuration.gypi
index e6a8911..ad8726b 100644
--- a/src/starboard/evergreen/shared/gyp_configuration.gypi
+++ b/src/starboard/evergreen/shared/gyp_configuration.gypi
@@ -26,6 +26,8 @@
     'cobalt_v8_buildtime_snapshot': 1,
     'cobalt_v8_enable_embedded_builtins': 1,
 
+    'cobalt_font_package': 'minimal',
+
     # Override that omits the "data" subdirectory.
     # TODO: Remove when omitted for all platforms in base_configuration.gypi.
     'sb_static_contents_output_data_dir': '<(PRODUCT_DIR)/content',
diff --git a/src/starboard/evergreen/shared/gyp_configuration.py b/src/starboard/evergreen/shared/gyp_configuration.py
index 3d9860f..d11e04c 100644
--- a/src/starboard/evergreen/shared/gyp_configuration.py
+++ b/src/starboard/evergreen/shared/gyp_configuration.py
@@ -29,7 +29,7 @@
                platform,
                asan_enabled_by_default=True,
                goma_supports_compiler=True,
-               sabi_json_path=None):
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     self.goma_supports_compiler = goma_supports_compiler
     self.sabi_json_path = sabi_json_path
     super(EvergreenConfiguration, self).__init__(platform,
@@ -48,8 +48,6 @@
     variables.update({
         'javascript_engine':
             'v8',
-        'cobalt_enable_jit':
-            1,
         'cobalt_repo_root':
             paths.REPOSITORY_ROOT,
         'include_path_platform_deploy_gypi':
@@ -90,8 +88,7 @@
     return filters
 
   __FILTERED_TESTS = {  # pylint: disable=invalid-name
-      'nplb': ['MemoryReportingTest.CapturesMemMapUnmap',
-               'MemoryReportingTest.CapturesOperatorDeleteNothrow',
+      'nplb': ['MemoryReportingTest.CapturesOperatorDeleteNothrow',
                'SbAudioSinkTest.*',
                'SbDrmTest.AnySupportedKeySystems'],
 
diff --git a/src/starboard/evergreen/shared/launcher.py b/src/starboard/evergreen/shared/launcher.py
index 5f18643..0be0a83 100644
--- a/src/starboard/evergreen/shared/launcher.py
+++ b/src/starboard/evergreen/shared/launcher.py
@@ -173,6 +173,18 @@
   def SendSuspend(self):
     return self.launcher.SendSuspend()
 
+  def SendConceal(self):
+    return self.launcher.SendConceal()
+
+  def SendFocus(self):
+    return self.launcher.SendFocus()
+
+  def SendFreeze(self):
+    return self.launcher.SendFreeze()
+
+  def SendStop(self):
+    return self.launcher.SendStop()
+
   def SupportsDeepLink(self):
     return self.launcher.SupportsDeepLink()
 
diff --git a/src/starboard/evergreen/x64/configuration_public.h b/src/starboard/evergreen/x64/configuration_public.h
index fe9c06d..89f8733 100644
--- a/src/starboard/evergreen/x64/configuration_public.h
+++ b/src/starboard/evergreen/x64/configuration_public.h
@@ -174,7 +174,7 @@
 
 // Whether this platform has and should use an MMAP function to map physical
 // memory to the virtual address space.
-#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#if SB_API_VERSION < 12
 #define SB_HAS_MMAP 1
 #endif
 
diff --git a/src/starboard/evergreen/x64/gyp_configuration.py b/src/starboard/evergreen/x64/gyp_configuration.py
index 9c572b0..86174cd 100644
--- a/src/starboard/evergreen/x64/gyp_configuration.py
+++ b/src/starboard/evergreen/x64/gyp_configuration.py
@@ -35,7 +35,7 @@
                platform_name='evergreen-x64',
                asan_enabled_by_default=False,
                goma_supports_compiler=True,
-               sabi_json_path=None):
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     # pylint: disable=useless-super-delegation
     super(EvergreenX64Configuration,
           self).__init__(platform_name, asan_enabled_by_default,
@@ -43,10 +43,10 @@
     self.AppendApplicationConfigurationPath(os.path.dirname(__file__))
     self._host_toolchain = None
 
-  def GetTargetToolchain(self):
-    return self.GetHostToolchain()
+  def GetTargetToolchain(self, **kwargs):
+    return self.GetHostToolchain(**kwargs)
 
-  def GetHostToolchain(self):
+  def GetHostToolchain(self, **kwargs):
     if not self._host_toolchain:
       if not hasattr(self, 'host_compiler_environment'):
         self.host_compiler_environment = build.GetHostCompilerEnvironment(
@@ -97,7 +97,8 @@
     return filters
 
   def GetVariables(self, configuration):
-    variables = super(EvergreenX64Configuration, self).GetVariables(configuration)
+    variables = super(EvergreenX64Configuration,
+                      self).GetVariables(configuration)
     variables.update({
         'include_path_platform_deploy_gypi':
             'starboard/evergreen/x64/platform_deploy.gypi',
@@ -107,4 +108,4 @@
 
 def CreatePlatformConfig():
   return EvergreenX64Configuration(
-      sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
+      sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/evergreen/x64/sbversion/12/atomic_public.h
similarity index 65%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/evergreen/x64/sbversion/12/atomic_public.h
index 0fbc0ef..64e82a1 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/evergreen/x64/sbversion/12/atomic_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_X64_SBVERSION_12_ATOMIC_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X64_SBVERSION_12_ATOMIC_PUBLIC_H_
 
-#include "starboard/raspi/shared/atomic_public.h"
+#include "starboard/evergreen/x64/atomic_public.h"
 
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#endif  // STARBOARD_EVERGREEN_X64_SBVERSION_12_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/raspi/0/configuration_public.h b/src/starboard/evergreen/x64/sbversion/12/configuration_public.h
similarity index 61%
rename from src/starboard/raspi/0/configuration_public.h
rename to src/starboard/evergreen/x64/sbversion/12/configuration_public.h
index d2c292b..2c411d7 100644
--- a/src/starboard/raspi/0/configuration_public.h
+++ b/src/starboard/evergreen/x64/sbversion/12/configuration_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,14 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// The Starboard configuration for Raspberry PI 1 Raspbian.
+// The Starboard configuration for x64. Other devices will have
+// specific Starboard implementations.
 
 // Other source files should never include this header directly, but should
 // include the generic "starboard/configuration.h" instead.
 
-#ifndef STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_X64_SBVERSION_12_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X64_SBVERSION_12_CONFIGURATION_PUBLIC_H_
 
-#include "starboard/raspi/shared/configuration_public.h"
+#include "starboard/evergreen/x64/configuration_public.h"
 
-#endif  // STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
+#endif  // STARBOARD_EVERGREEN_X64_SBVERSION_12_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/evergreen/x64/sbversion/12/gyp_configuration.gypi b/src/starboard/evergreen/x64/sbversion/12/gyp_configuration.gypi
new file mode 100644
index 0000000..fa4e5a1
--- /dev/null
+++ b/src/starboard/evergreen/x64/sbversion/12/gyp_configuration.gypi
@@ -0,0 +1,58 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+  'variables': {
+    'yasm_exists': 1,
+    'sb_target_platform': 'evergreen-x64',
+
+    'compiler_flags': [
+      '-isystem<(cobalt_repo_root)/third_party/musl/arch/x86_64',
+    ],
+  },
+
+  'target_defaults': {
+    'defines' : [
+      # Ensure that the Starboardized __external_threading file is included.
+      '_LIBCPP_HAS_THREAD_API_EXTERNAL',
+      # Ensure that only the forward declarations and type definitions are included
+      # in __external_threading.
+      '_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL',
+      # Enable GNU extensions to get prototypes like ffsl.
+      '_GNU_SOURCE=1',
+    ],
+    'default_configuration': 'evergreen-x64-sbversion-12_debug',
+    'configurations': {
+      'evergreen-x64-sbversion-12_debug': {
+        'inherit_from': ['debug_base'],
+      },
+      'evergreen-x64-sbversion-12_devel': {
+        'inherit_from': ['devel_base'],
+      },
+      'evergreen-x64-sbversion-12_qa': {
+        'inherit_from': ['qa_base'],
+      },
+      'evergreen-x64-sbversion-12_gold': {
+        'inherit_from': ['gold_base'],
+      },
+    }, # end of configurations
+  },
+  'includes': [
+    '<(DEPTH)/starboard/evergreen/shared/gyp_configuration.gypi',
+    '<(DEPTH)/starboard/evergreen/shared/compiler_flags.gypi',
+  ],
+}
diff --git a/src/starboard/evergreen/x64/sbversion/12/gyp_configuration.py b/src/starboard/evergreen/x64/sbversion/12/gyp_configuration.py
new file mode 100644
index 0000000..a5ce04a
--- /dev/null
+++ b/src/starboard/evergreen/x64/sbversion/12/gyp_configuration.py
@@ -0,0 +1,22 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Starboard evergreen-x64 platform configuration for gyp_cobalt."""
+
+from starboard.evergreen.x64 import gyp_configuration as parent_configuration
+
+
+def CreatePlatformConfig():
+  return parent_configuration.EvergreenX64Configuration(
+      platform_name='evergreen-x64-sbversion-12',
+      sabi_json_path='starboard/sabi/x64/sysv/sabi-v12.json')
diff --git a/src/starboard/raspi/0/starboard_platform.gyp b/src/starboard/evergreen/x64/sbversion/12/starboard_platform.gyp
similarity index 67%
copy from src/starboard/raspi/0/starboard_platform.gyp
copy to src/starboard/evergreen/x64/sbversion/12/starboard_platform.gyp
index 021af7c..ad9035d 100644
--- a/src/starboard/raspi/0/starboard_platform.gyp
+++ b/src/starboard/evergreen/x64/sbversion/12/starboard_platform.gyp
@@ -1,4 +1,4 @@
-# Copyright 2017 The Cobalt Authors. All Rights Reserved.
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -11,8 +11,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 {
   'includes': [
-    '../shared/starboard_platform.gypi',
+    # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file.  The idea
+    # is that we just want this file to *be* the parent gyp file.
+    '<(DEPTH)/starboard/evergreen/x64/starboard_platform.gyp',
   ],
 }
diff --git a/src/starboard/evergreen/x64/sbversion/12/thread_types_public.h b/src/starboard/evergreen/x64/sbversion/12/thread_types_public.h
new file mode 100644
index 0000000..2695e58
--- /dev/null
+++ b/src/starboard/evergreen/x64/sbversion/12/thread_types_public.h
@@ -0,0 +1,23 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file was initially generated by starboard/tools/create_derived_build.py,
+// though it may have been modified since its creation.
+
+#ifndef STARBOARD_EVERGREEN_X64_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X64_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+
+#include "starboard/evergreen/x64/thread_types_public.h"
+
+#endif  // STARBOARD_EVERGREEN_X64_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/evergreen/x86/gyp_configuration.py b/src/starboard/evergreen/x86/gyp_configuration.py
index a67484c..5ac4c8e 100644
--- a/src/starboard/evergreen/x86/gyp_configuration.py
+++ b/src/starboard/evergreen/x86/gyp_configuration.py
@@ -35,17 +35,17 @@
                platform_name='evergreen-x86',
                asan_enabled_by_default=False,
                goma_supports_compiler=True,
-               sabi_json_path=None):
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     # pylint: disable=useless-super-delegation
     super(EvergreenX86Configuration,
           self).__init__(platform_name, asan_enabled_by_default,
                          goma_supports_compiler, sabi_json_path)
     self._host_toolchain = None
 
-  def GetTargetToolchain(self):
-    return self.GetHostToolchain()
+  def GetTargetToolchain(self, **kwargs):
+    return self.GetHostToolchain(**kwargs)
 
-  def GetHostToolchain(self):
+  def GetHostToolchain(self, **kwargs):
     if not self._host_toolchain:
       if not hasattr(self, 'host_compiler_environment'):
         self.host_compiler_environment = build.GetHostCompilerEnvironment(
@@ -98,4 +98,4 @@
 
 def CreatePlatformConfig():
   return EvergreenX86Configuration(
-      sabi_json_path='starboard/sabi/x86/sabi.json')
+      sabi_json_path='starboard/sabi/x86/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/evergreen/x86/sbversion/12/atomic_public.h
similarity index 65%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/evergreen/x86/sbversion/12/atomic_public.h
index 0fbc0ef..216d7b6 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/evergreen/x86/sbversion/12/atomic_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_X86_SBVERSION_12_ATOMIC_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X86_SBVERSION_12_ATOMIC_PUBLIC_H_
 
-#include "starboard/raspi/shared/atomic_public.h"
+#include "starboard/evergreen/x86/atomic_public.h"
 
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#endif  // STARBOARD_EVERGREEN_X86_SBVERSION_12_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/raspi/0/configuration_public.h b/src/starboard/evergreen/x86/sbversion/12/configuration_public.h
similarity index 61%
copy from src/starboard/raspi/0/configuration_public.h
copy to src/starboard/evergreen/x86/sbversion/12/configuration_public.h
index d2c292b..a8dfb83 100644
--- a/src/starboard/raspi/0/configuration_public.h
+++ b/src/starboard/evergreen/x86/sbversion/12/configuration_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,14 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// The Starboard configuration for Raspberry PI 1 Raspbian.
+// The Starboard configuration for x86. Other devices will have
+// specific Starboard implementations.
 
 // Other source files should never include this header directly, but should
 // include the generic "starboard/configuration.h" instead.
 
-#ifndef STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_X86_SBVERSION_12_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X86_SBVERSION_12_CONFIGURATION_PUBLIC_H_
 
-#include "starboard/raspi/shared/configuration_public.h"
+#include "starboard/evergreen/x86/configuration_public.h"
 
-#endif  // STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
+#endif  // STARBOARD_EVERGREEN_X86_SBVERSION_12_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/evergreen/x86/sbversion/12/gyp_configuration.gypi b/src/starboard/evergreen/x86/sbversion/12/gyp_configuration.gypi
new file mode 100644
index 0000000..9c5fb14
--- /dev/null
+++ b/src/starboard/evergreen/x86/sbversion/12/gyp_configuration.gypi
@@ -0,0 +1,58 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+  'variables': {
+    'yasm_exists': 1,
+    'sb_target_platform': 'evergreen-x86',
+
+    'compiler_flags': [
+      '-isystem<(cobalt_repo_root)/third_party/musl/arch/i386',
+    ],
+  },
+
+  'target_defaults': {
+    'defines' : [
+      # Ensure that the Starboardized __external_threading file is included.
+      '_LIBCPP_HAS_THREAD_API_EXTERNAL',
+      # Ensure that only the forward declarations and type definitions are included
+      # in __external_threading.
+      '_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL',
+      # Enable GNU extensions to get prototypes like ffsl.
+      '_GNU_SOURCE=1',
+    ],
+    'default_configuration': 'evergreen-x86-sbversion-12_debug',
+    'configurations': {
+      'evergreen-x86-sbversion-12_debug': {
+        'inherit_from': ['debug_base'],
+      },
+      'evergreen-x86-sbversion-12_devel': {
+        'inherit_from': ['devel_base'],
+      },
+      'evergreen-x86-sbversion-12_qa': {
+        'inherit_from': ['qa_base'],
+      },
+      'evergreen-x86-sbversion-12_gold': {
+        'inherit_from': ['gold_base'],
+      },
+    }, # end of configurations
+  },
+  'includes': [
+    '<(DEPTH)/starboard/evergreen/shared/gyp_configuration.gypi',
+    '<(DEPTH)/starboard/evergreen/shared/compiler_flags.gypi',
+  ],
+}
diff --git a/src/starboard/evergreen/x86/sbversion/12/gyp_configuration.py b/src/starboard/evergreen/x86/sbversion/12/gyp_configuration.py
new file mode 100644
index 0000000..0b040a4
--- /dev/null
+++ b/src/starboard/evergreen/x86/sbversion/12/gyp_configuration.py
@@ -0,0 +1,22 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Starboard evergreen-x86 platform configuration for gyp_cobalt."""
+
+from starboard.evergreen.x86 import gyp_configuration as parent_configuration
+
+
+def CreatePlatformConfig():
+  return parent_configuration.EvergreenX86Configuration(
+      platform_name='evergreen-x86-sbversion-12',
+      sabi_json_path='starboard/sabi/x86/sabi-v12.json')
diff --git a/src/starboard/raspi/0/starboard_platform.gyp b/src/starboard/evergreen/x86/sbversion/12/starboard_platform.gyp
similarity index 67%
copy from src/starboard/raspi/0/starboard_platform.gyp
copy to src/starboard/evergreen/x86/sbversion/12/starboard_platform.gyp
index 021af7c..8fa33ef 100644
--- a/src/starboard/raspi/0/starboard_platform.gyp
+++ b/src/starboard/evergreen/x86/sbversion/12/starboard_platform.gyp
@@ -1,4 +1,4 @@
-# Copyright 2017 The Cobalt Authors. All Rights Reserved.
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -11,8 +11,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 {
   'includes': [
-    '../shared/starboard_platform.gypi',
+    # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file.  The idea
+    # is that we just want this file to *be* the parent gyp file.
+    '<(DEPTH)/starboard/evergreen/shared/starboard_platform.gyp',
   ],
 }
diff --git a/src/starboard/evergreen/x86/sbversion/12/thread_types_public.h b/src/starboard/evergreen/x86/sbversion/12/thread_types_public.h
new file mode 100644
index 0000000..bca9e4d
--- /dev/null
+++ b/src/starboard/evergreen/x86/sbversion/12/thread_types_public.h
@@ -0,0 +1,23 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file was initially generated by starboard/tools/create_derived_build.py,
+// though it may have been modified since its creation.
+
+#ifndef STARBOARD_EVERGREEN_X86_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X86_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+
+#include "starboard/evergreen/x86/thread_types_public.h"
+
+#endif  // STARBOARD_EVERGREEN_X86_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/examples/glclear/main.cc b/src/starboard/examples/glclear/main.cc
index d74d90f..a508671 100644
--- a/src/starboard/examples/glclear/main.cc
+++ b/src/starboard/examples/glclear/main.cc
@@ -172,7 +172,7 @@
   SbEglInt32 context_attrib_list[] = {
       SB_EGL_CONTEXT_CLIENT_VERSION, 3, SB_EGL_NONE,
   };
-#if SB_API_VERSION < SB_GLES3_DEPRECATED_VERSION && defined(GLES3_SUPPORTED)
+#if SB_API_VERSION < 12 && defined(GLES3_SUPPORTED)
   // Attempt to create an OpenGL ES 3.0 context.
   context_ = EGL_CALL_SIMPLE(eglCreateContext(
       display_, config, SB_EGL_NO_CONTEXT, context_attrib_list));
diff --git a/src/starboard/examples/window/main.cc b/src/starboard/examples/window/main.cc
index 2b01909..27c80a0 100644
--- a/src/starboard/examples/window/main.cc
+++ b/src/starboard/examples/window/main.cc
@@ -45,10 +45,20 @@
       g_window = SbWindowCreate(NULL);
       SB_CHECK(SbWindowIsValid(g_window));
 
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+      SB_LOG(INFO) << "    F1 - Blur";
+      SB_LOG(INFO) << "    F2 - Focus";
+      SB_LOG(INFO) << "    F3 - Conceal";
+      SB_LOG(INFO) << "    F4 - Freeze";
+      SB_LOG(INFO) << "    F5 - Stop";
+#else
       SB_LOG(INFO) << "    F1 - Pause";
       SB_LOG(INFO) << "    F2 - Unpause";
       SB_LOG(INFO) << "    F3 - Suspend";
       SB_LOG(INFO) << "    F5 - Stop";
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
       break;
     }
     case kSbEventTypeInput: {
@@ -85,7 +95,29 @@
           SB_LOG(INFO) << keys.str();
         }
       }
-
+#if  SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+     SB_HAS(CONCEALED_STATE)
+      switch (data->key) {
+        case kSbKeyF1:
+          SbSystemRequestBlur();
+          break;
+        case kSbKeyF2:
+          SbSystemRequestFocus();
+          break;
+        case kSbKeyF3:
+          SbSystemRequestConceal();
+          break;
+        case kSbKeyF4:
+          SbSystemRequestFreeze();
+          break;
+        case kSbKeyF5:
+          SbSystemRequestStop(0);
+          break;
+        default:
+          // Do nothing.
+          break;
+      }
+#else
       switch (data->key) {
         case kSbKeyF1:
           SbSystemRequestPause();
@@ -103,8 +135,42 @@
           // Do nothing.
           break;
       }
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
       break;
     }
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+    case kSbEventTypeBlur: {
+      SB_LOG(INFO) << "BLUR";
+      break;
+    }
+    case kSbEventTypeConceal: {
+      SB_LOG(INFO) << "CONCEAL";
+      break;
+    }
+    case kSbEventTypeFreeze: {
+      SB_LOG(INFO) << "FREEZE";
+      break;
+    }
+    case kSbEventTypeStop: {
+      SB_LOG(INFO) << "STOP";
+      SbWindowDestroy(g_window);
+      break;
+    }
+    case kSbEventTypeUnfreeze: {
+      SB_LOG(INFO) << "UNFREEZE";
+      break;
+    }
+    case kSbEventTypeReveal: {
+      SB_LOG(INFO) << "REVEAL";
+      break;
+    }
+    case kSbEventTypeFocus: {
+      SB_LOG(INFO) << "FOCUS";
+      break;
+    }
+#else
     case kSbEventTypePause: {
       SB_LOG(INFO) << "PAUSE";
       break;
@@ -126,6 +192,8 @@
       SB_LOG(INFO) << "UNPAUSE";
       break;
     }
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
     default:
       SB_LOG(INFO) << "Event Type " << event->type << " not handled.";
       break;
diff --git a/src/starboard/file.h b/src/starboard/file.h
index 11f7494..66d93cb 100644
--- a/src/starboard/file.h
+++ b/src/starboard/file.h
@@ -160,7 +160,7 @@
 // |file|: The absolute path of the file to be closed.
 SB_EXPORT bool SbFileClose(SbFile file);
 
-#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#if SB_API_VERSION >= 12
 
 // Replaces the content of the file at |path| with |data|. Returns whether the
 // contents of the file were replaced. The replacement of the content is an
@@ -173,7 +173,7 @@
                                    const char* data,
                                    int64_t data_size);
 
-#endif  // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#endif  // SB_API_VERSION >= 12
 
 // Changes the current read/write position in |file|. The return value
 // identifies the resultant current read/write position in the file (relative
diff --git a/src/starboard/input.h b/src/starboard/input.h
index 3c608bf..ccfa876 100644
--- a/src/starboard/input.h
+++ b/src/starboard/input.h
@@ -88,13 +88,12 @@
   // Produces |Move|, |Press|, and |Unpress| events.
   kSbInputDeviceTypeTouchPad,
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
   // Keyboard input from an on screen keyboard.
   //
   // Produces |Input| events.
   kSbInputDeviceTypeOnScreenKeyboard,
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
 } SbInputDeviceType;
 
@@ -134,11 +133,10 @@
   // Wheel movement. Provides relative movements of the |Mouse| wheel.
   kSbInputEventTypeWheel,
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
   // https://w3c.github.io/uievents/#event-type-input
   kSbInputEventTypeInput,
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
 } SbInputEventType;
 
@@ -215,8 +213,7 @@
   // towards the user (y). Use (NaN, NaN) for devices that do not report tilt.
   // This value is used for input events with device type mouse or touch screen.
   SbInputVector tilt;
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
   // The text to input for events of type |Input|.
   const char* input_text;
 
diff --git a/src/starboard/linux/shared/configuration.cc b/src/starboard/linux/shared/configuration.cc
index bc5a3b1..9cbc88f 100644
--- a/src/starboard/linux/shared/configuration.cc
+++ b/src/starboard/linux/shared/configuration.cc
@@ -24,6 +24,9 @@
 namespace {
 
 int CobaltEglSwapInterval() {
+  // This platform uses a compositor to present the rendering output, so
+  // set the swap interval to update the buffer immediately. That buffer
+  // will then be presented by the compositor on its own time.
   return 0;
 }
 
diff --git a/src/starboard/linux/shared/configuration_constants.cc b/src/starboard/linux/shared/configuration_constants.cc
index f95a9f3..e3ad2c7 100644
--- a/src/starboard/linux/shared/configuration_constants.cc
+++ b/src/starboard/linux/shared/configuration_constants.cc
@@ -16,7 +16,7 @@
 
 #include "starboard/configuration_constants.h"
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
 
 // Determines the threshhold of allocation size that should be done with mmap
 // (if available), rather than allocated within the core heap.
@@ -54,9 +54,6 @@
 // Allow ac3 and ec3 support
 const bool kSbHasAc3Audio = true;
 
-// Specifies whether this platform updates audio frames asynchronously.
-const bool kSbHasAsyncAudioFramesReporting = false;
-
 // Specifies whether this platform has webm/vp9 support.  This should be set to
 // non-zero on platforms with webm/vp9 support.
 const bool kSbHasMediaWebmVp9Support = false;
@@ -147,4 +144,4 @@
 // The maximum number of users that can be signed in at the same time.
 const uint32_t kSbUserMaxSignedIn = 1;
 
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/linux/shared/configuration_public.h b/src/starboard/linux/shared/configuration_public.h
index f7f15e7..1c32935 100644
--- a/src/starboard/linux/shared/configuration_public.h
+++ b/src/starboard/linux/shared/configuration_public.h
@@ -132,62 +132,62 @@
 
 // --- Filesystem Configuration ----------------------------------------------
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The current platform's maximum length of the name of a single directory
 // entry, not including the absolute path.
 #define SB_FILE_MAX_NAME 64
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The current platform's maximum length of an absolute path.
 #define SB_FILE_MAX_PATH 4096
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The current platform's maximum number of files that can be opened at the
 // same time by one process.
 #define SB_FILE_MAX_OPEN 256
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The current platform's file path component separator character. This is the
 // character that appears after a directory in a file path. For example, the
 // absolute canonical path of the file "/path/to/a/file.txt" uses '/' as a path
 // component separator character.
 #define SB_FILE_SEP_CHAR '/'
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The current platform's alternate file path component separator character.
 // This is like SB_FILE_SEP_CHAR, except if your platform supports an alternate
 // character, then you can place that here. For example, on windows machines,
 // the primary separator character is probably '\', but the alternate is '/'.
 #define SB_FILE_ALT_SEP_CHAR '/'
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The current platform's search path component separator character. When
 // specifying an ordered list of absolute paths of directories to search for a
 // given reason, this is the character that appears between entries. For
 // example, the search path of "/etc/search/first:/etc/search/second" uses ':'
 // as a search path component separator character.
 #define SB_PATH_SEP_CHAR ':'
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The string form of SB_FILE_SEP_CHAR.
 #define SB_FILE_SEP_STRING "/"
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The string form of SB_FILE_ALT_SEP_CHAR.
 #define SB_FILE_ALT_SEP_STRING "/"
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The string form of SB_PATH_SEP_CHAR.
 #define SB_PATH_SEP_STRING ":"
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
 // --- Graphics Configuration ------------------------------------------------
 
@@ -195,19 +195,19 @@
 // API. The basic requirement is a scaled, clipped, alpha-blended blit.
 #define SB_HAS_BLITTER 0
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Specifies the preferred byte order of color channels in a pixel. Refer to
 // starboard/configuration.h for the possible values. EGL/GLES platforms should
 // generally prefer a byte order of RGBA, regardless of endianness.
 #define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_RGBA
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
 // Indicates whether or not the given platform supports bilinear filtering.
 // This can be checked to enable/disable renderer tests that verify that this is
 // working properly.
 #define SB_HAS_BILINEAR_FILTERING_SUPPORT 1
 
-#if SB_API_VERSION < SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 // Whether the current platform should frequently flip their display buffer.
 // If this is not required (e.g. SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER is set
 // to 0), then optimizations where the display buffer is not flipped if the
@@ -224,62 +224,62 @@
 
 // --- Media Configuration ---------------------------------------------------
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The maximum audio bitrate the platform can decode.  The following value
 // equals to 5M bytes per seconds which is more than enough for compressed
 // audio.
 #define SB_MEDIA_MAX_AUDIO_BITRATE_IN_BITS_PER_SECOND (40 * 1024 * 1024)
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The maximum video bitrate the platform can decode.  The following value
 // equals to 25M bytes per seconds which is more than enough for compressed
 // video.
 #define SB_MEDIA_MAX_VIDEO_BITRATE_IN_BITS_PER_SECOND (200 * 1024 * 1024)
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Specifies whether this platform has webm/vp9 support.  This should be set to
 // non-zero on platforms with webm/vp9 support.
 #define SB_HAS_MEDIA_WEBM_VP9_SUPPORT 0
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Specifies whether this platform updates audio frames asynchronously.  In such
 // case an extra parameter will be added to |SbAudioSinkConsumeFramesFunc| to
 // indicate the absolute time that the consumed audio frames are reported.
 // Check document for |SbAudioSinkConsumeFramesFunc| in audio_sink.h for more
 // details.
 #define SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING 0
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION <  12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Specifies the stack size for threads created inside media stack.  Set to 0 to
 // use the default thread stack size.  Set to non-zero to explicitly set the
 // stack size for media stack threads.
 #define SB_MEDIA_THREAD_STACK_SIZE 0U
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Allow ac3 and ec3 support
 #define SB_HAS_AC3_AUDIO 1
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
 // --- Decoder-only Params ---
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Specifies how media buffers must be aligned on this platform as some
 // decoders may have special requirement on the alignment of buffers being
 // decoded.
 #define SB_MEDIA_BUFFER_ALIGNMENT 128U
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Specifies how video frame buffers must be aligned on this platform.
 #define SB_MEDIA_VIDEO_FRAME_ALIGNMENT 256U
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The encoded video frames are compressed in different ways, their decoding
 // time can vary a lot.  Occasionally a single frame can take longer time to
 // decode than the average time per frame.  The player has to cache some frames
@@ -289,27 +289,27 @@
 // Specify the number of video frames to be cached before the playback starts.
 // Note that set this value too large may increase the playback start delay.
 #define SB_MEDIA_MAXIMUM_VIDEO_PREROLL_FRAMES 4
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Specify the number of video frames to be cached during playback.  A large
 // value leads to more stable fps but also causes the app to use more memory.
 #define SB_MEDIA_MAXIMUM_VIDEO_FRAMES 12
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
 // --- Memory Configuration --------------------------------------------------
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The memory page size, which controls the size of chunks on memory that
 // allocators deal with, and the alignment of those chunks. This doesn't have to
 // be the hardware-defined physical page size, but it should be a multiple of
 // it.
 #define SB_MEMORY_PAGE_SIZE 4096
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
 // Whether this platform has and should use an MMAP function to map physical
 // memory to the virtual address space.
-#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#if SB_API_VERSION < 12
 #define SB_HAS_MMAP 1
 #endif
 
@@ -317,34 +317,34 @@
 // required for platforms that want to JIT.
 #define SB_CAN_MAP_EXECUTABLE_MEMORY 1
 
-#if SB_API_VERSION < SB_VIRTUAL_REGIONS_FLAG_DEPRECATED
+#if SB_API_VERSION < 12
 // Whether this platform has and should use an growable heap (e.g. with sbrk())
 // to map physical memory to the virtual address space.
 #define SB_HAS_VIRTUAL_REGIONS 0
-#endif  // SB_API_VERSION < SB_VIRTUAL_REGIONS_FLAG_DEPRECATED
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Specifies the alignment for IO Buffers, in bytes. Some low-level network APIs
 // may require buffers to have a specific alignment, and this is the place to
 // specify that.
 #define SB_NETWORK_IO_BUFFER_ALIGNMENT 16
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Determines the alignment that allocations should have on this platform.
 #define SB_MALLOC_ALIGNMENT ((size_t)16U)
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Determines the threshhold of allocation size that should be done with mmap
 // (if available), rather than allocated within the core heap.
 #define SB_DEFAULT_MMAP_THRESHOLD ((size_t)(256 * 1024U))
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Defines the path where memory debugging logs should be written to.
 #define SB_MEMORY_LOG_PATH "/tmp/starboard"
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
 // --- Network Configuration -------------------------------------------------
 
@@ -356,32 +356,32 @@
 
 // --- Thread Configuration --------------------------------------------------
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // On default Linux desktop, you must be a superuser in order to set real time
 // scheduling on threads.
 #define SB_HAS_THREAD_PRIORITY_SUPPORT 0
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Defines the maximum number of simultaneous threads for this platform. Some
 // platforms require sharing thread handles with other kinds of system handles,
 // like mutexes, so we want to keep this managable.
 #define SB_MAX_THREADS 90
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The maximum number of thread local storage keys supported by this platform.
 #define SB_MAX_THREAD_LOCAL_KEYS 512
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The maximum length of the name for a thread, including the NULL-terminator.
 #define SB_MAX_THREAD_NAME_LENGTH 16
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
 // --- Tuneable Parameters ---------------------------------------------------
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // Specifies the network receive buffer size in bytes, set via
 // SbSocketSetReceiveBufferSize().
 //
@@ -395,14 +395,14 @@
 // If your platform does not have a good TCP auto-tuning mechanism,
 // a setting of (128 * 1024) here is recommended.
 #define SB_NETWORK_RECEIVE_BUFFER_SIZE (0)
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
 // --- User Configuration ----------------------------------------------------
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION < 12
 // The maximum number of users that can be signed in at the same time.
 #define SB_USER_MAX_SIGNED_IN 1
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION < 12
 
 // --- Timing API ------------------------------------------------------------
 
diff --git a/src/starboard/linux/shared/gyp_configuration.py b/src/starboard/linux/shared/gyp_configuration.py
index 7c1b3da..a635fda 100644
--- a/src/starboard/linux/shared/gyp_configuration.py
+++ b/src/starboard/linux/shared/gyp_configuration.py
@@ -28,7 +28,7 @@
                platform,
                asan_enabled_by_default=True,
                goma_supports_compiler=True,
-               sabi_json_path=None):
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     self.goma_supports_compiler = goma_supports_compiler
     self.sabi_json_path = sabi_json_path
     super(LinuxConfiguration, self).__init__(platform, asan_enabled_by_default)
@@ -47,8 +47,6 @@
     variables.update({
         'javascript_engine':
             'v8',
-        'cobalt_enable_jit':
-            1,
         'include_path_platform_deploy_gypi':
             'starboard/linux/shared/platform_deploy.gypi',
     })
diff --git a/src/starboard/linux/shared/launcher.py b/src/starboard/linux/shared/launcher.py
index 5ade939..f189c51 100644
--- a/src/starboard/linux/shared/launcher.py
+++ b/src/starboard/linux/shared/launcher.py
@@ -128,6 +128,46 @@
     else:
       sys.stderr.write("Cannot send suspend to executable; it is closed.\n")
 
+  def SendConceal(self):
+    """Sends conceal to the launcher's executable."""
+    sys.stderr.write("\n***Sending conceal signal to executable***\n")
+    if self.proc:
+      self.proc.send_signal(signal.SIGUSR1)
+      # Wait for process status change in Linux system.
+      self.WaitForProcessStatus("S", STATUS_CHANGE_TIMEOUT)
+    else:
+      sys.stderr.write("Cannot send conceal to executable; it is closed.\n")
+
+  def SendFocus(self):
+    """Sends focus to the launcher's executable."""
+    sys.stderr.write("\n***Sending focus signal to executable***\n")
+    if self.proc:
+      self.proc.send_signal(signal.SIGCONT)
+      # Wait for process status change in Linux system.
+      self.WaitForProcessStatus("R", STATUS_CHANGE_TIMEOUT)
+    else:
+      sys.stderr.write("Cannot send unpause to executable; it is closed.\n")
+
+  def SendFreeze(self):
+    """Sends freeze to the launcher's executable."""
+    sys.stderr.write("\n***Sending freeze signal to executable***\n")
+    if self.proc:
+      self.proc.send_signal(signal.SIGTSTP)
+      # Wait for process status change in Linux system.
+      self.WaitForProcessStatus("T", STATUS_CHANGE_TIMEOUT)
+    else:
+      sys.stderr.write("Cannot send freeze to executable; it is closed.\n")
+
+  def SendStop(self):
+    """Sends stop to the launcher's executable."""
+    sys.stderr.write("\n***Sending stop signal to executable***\n")
+    if self.proc:
+      self.proc.send_signal(signal.SIGPWR)
+      # Wait for process status change in Linux system.
+      self.WaitForProcessStatus("T", STATUS_CHANGE_TIMEOUT)
+    else:
+      sys.stderr.write("Cannot send stop to executable; it is closed.\n")
+
   def SupportsDeepLink(self):
     return True
 
@@ -136,7 +176,7 @@
     # this happens.
     connection_attempts = 3
     return send_link.SendLink(
-        os.path.basename(self.executable), link, connection_attempts)
+        os.path.basename(self.executable), link, connection_attempts) == 0
 
   def WaitForProcessStatus(self, target_status, timeout):
     """Wait for Cobalt to turn to target status within specified timeout limit.
diff --git a/src/starboard/linux/shared/libraries.gypi b/src/starboard/linux/shared/libraries.gypi
index 45fccd0..55f16ba 100644
--- a/src/starboard/linux/shared/libraries.gypi
+++ b/src/starboard/linux/shared/libraries.gypi
@@ -14,11 +14,6 @@
 
 {
   'variables': {
-    # This platform uses a compositor to present the rendering output, so
-    # set the swap interval to update the buffer immediately. That buffer
-    # will then be presented by the compositor on its own time.
-    'cobalt_egl_swap_interval': 0,
-
     # Hook into the swap buffers call to facilitate synchronization of the
     # OpenGL output with the punch-through video layer.
     'linker_flags': [
diff --git a/src/starboard/linux/shared/media_is_audio_supported.cc b/src/starboard/linux/shared/media_is_audio_supported.cc
index 5128fb0..8054684 100644
--- a/src/starboard/linux/shared/media_is_audio_supported.cc
+++ b/src/starboard/linux/shared/media_is_audio_supported.cc
@@ -20,16 +20,16 @@
 #include "starboard/media.h"
 
 bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
                              const char* content_type,
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
                              int64_t bitrate) {
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
   if (!content_type) {
     SB_LOG(WARNING) << "|content_type| cannot be nullptr.";
     return false;
   }
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
 
   if (audio_codec == kSbMediaAudioCodecAac) {
     return bitrate <= kSbMediaMaxAudioBitrateInBitsPerSecond;
@@ -39,15 +39,14 @@
     return bitrate <= kSbMediaMaxAudioBitrateInBitsPerSecond;
   }
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    defined(SB_HAS_AC3_AUDIO)
+#if SB_API_VERSION >= 12 || defined(SB_HAS_AC3_AUDIO)
   if (kSbHasAc3Audio) {
     if (audio_codec == kSbMediaAudioCodecAc3 ||
         audio_codec == kSbMediaAudioCodecEac3) {
       return bitrate <= kSbMediaMaxAudioBitrateInBitsPerSecond;
     }
   }
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // defined(SB_HAS_AC3_AUDIO)
 
   return false;
diff --git a/src/starboard/linux/shared/media_is_video_supported.cc b/src/starboard/linux/shared/media_is_video_supported.cc
index a323a8c..0de11ef 100644
--- a/src/starboard/linux/shared/media_is_video_supported.cc
+++ b/src/starboard/linux/shared/media_is_video_supported.cc
@@ -32,9 +32,9 @@
 using starboard::shared::vpx::is_vpx_supported;
 
 bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
                              const char* content_type,
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
 #if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
                              int profile,
                              int level,
@@ -53,15 +53,13 @@
 #endif  // SB_API_VERSION < 11
 
 #if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
-  SB_UNREFERENCED_PARAMETER(profile);
-  SB_UNREFERENCED_PARAMETER(level);
 
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
   if (!content_type) {
     SB_LOG(WARNING) << "|content_type| cannot be nullptr.";
     return false;
   }
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
 
   if (!IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id)) {
     if (bit_depth != 10 && bit_depth != 12) {
diff --git a/src/starboard/linux/shared/oemcrypto_engine_device_properties_linux.cc b/src/starboard/linux/shared/oemcrypto_engine_device_properties_linux.cc
deleted file mode 100644
index a4b623f..0000000
--- a/src/starboard/linux/shared/oemcrypto_engine_device_properties_linux.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "third_party/ce_cdm/oemcrypto/mock/src/oemcrypto_engine_mock.h"
-
-#include "starboard/media.h"
-
-namespace {
-const OEMCrypto_HDCP_Capability kWidevineMaximumHdcpVersion = HDCP_V1;
-}  // namespace
-
-namespace wvoec_mock {
-
-class CryptoEngineLinux : public CryptoEngine {
- public:
-  explicit CryptoEngineLinux(std::auto_ptr<wvcdm::FileSystem> file_system)
-      : CryptoEngine(file_system) {}
-
-  OEMCrypto_HDCP_Capability config_current_hdcp_capability() override {
-    return HDCP_NONE;
-  }
-
-  OEMCrypto_HDCP_Capability config_maximum_hdcp_capability() override {
-    return kWidevineMaximumHdcpVersion;
-  }
-
-  // Max buffer size for encoded buffer.
-  size_t max_buffer_size() override { return 3840 * 2160 * 2; }
-};
-
-CryptoEngine* CryptoEngine::MakeCryptoEngine(
-    std::auto_ptr<wvcdm::FileSystem> file_system) {
-  return new CryptoEngineLinux(file_system);
-}
-
-}  // namespace wvoec_mock
diff --git a/src/starboard/linux/shared/player_components_factory.cc b/src/starboard/linux/shared/player_components_factory.cc
index 6c9b2bb..2171f7e 100644
--- a/src/starboard/linux/shared/player_components_factory.cc
+++ b/src/starboard/linux/shared/player_components_factory.cc
@@ -201,9 +201,6 @@
 bool VideoDecoder::OutputModeSupported(SbPlayerOutputMode output_mode,
                                        SbMediaVideoCodec codec,
                                        SbDrmSystem drm_system) {
-  SB_UNREFERENCED_PARAMETER(codec);
-  SB_UNREFERENCED_PARAMETER(drm_system);
-
   bool has_gles_support = false;
 
 #if SB_API_VERSION >= 11
diff --git a/src/starboard/linux/shared/starboard_platform.gypi b/src/starboard/linux/shared/starboard_platform.gypi
index fdebe88..2167157 100644
--- a/src/starboard/linux/shared/starboard_platform.gypi
+++ b/src/starboard/linux/shared/starboard_platform.gypi
@@ -235,6 +235,8 @@
       '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc',
       '<(DEPTH)/starboard/shared/signal/suspend_signals.cc',
       '<(DEPTH)/starboard/shared/signal/suspend_signals.h',
+      '<(DEPTH)/starboard/shared/signal/system_request_conceal.cc',
+      '<(DEPTH)/starboard/shared/signal/system_request_freeze.cc',
       '<(DEPTH)/starboard/shared/signal/system_request_suspend.cc',
       '<(DEPTH)/starboard/shared/starboard/application.cc',
       '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
@@ -285,6 +287,7 @@
       '<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc',
       '<(DEPTH)/starboard/shared/starboard/media/mime_type.cc',
       '<(DEPTH)/starboard/shared/starboard/media/mime_type.h',
+      '<(DEPTH)/starboard/shared/starboard/memory.cc',
       '<(DEPTH)/starboard/shared/starboard/new.cc',
       '<(DEPTH)/starboard/shared/starboard/player/decoded_audio_internal.cc',
       '<(DEPTH)/starboard/shared/starboard/player/decoded_audio_internal.h',
@@ -318,7 +321,10 @@
       '<(DEPTH)/starboard/shared/starboard/string_copy_wide.cc',
       '<(DEPTH)/starboard/shared/starboard/string_duplicate.cc',
       '<(DEPTH)/starboard/shared/starboard/system_get_random_uint64.cc',
+      '<(DEPTH)/starboard/shared/starboard/system_request_blur.cc',
+      '<(DEPTH)/starboard/shared/starboard/system_request_focus.cc',
       '<(DEPTH)/starboard/shared/starboard/system_request_pause.cc',
+      '<(DEPTH)/starboard/shared/starboard/system_request_reveal.cc',
       '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc',
       '<(DEPTH)/starboard/shared/starboard/system_request_unpause.cc',
       '<(DEPTH)/starboard/shared/starboard/system_supports_resume.cc',
@@ -419,6 +425,7 @@
           '<(DEPTH)/starboard/shared/starboard/drm/drm_close_session.cc',
           '<(DEPTH)/starboard/shared/starboard/drm/drm_destroy_system.cc',
           '<(DEPTH)/starboard/shared/starboard/drm/drm_generate_session_update_request.cc',
+          '<(DEPTH)/starboard/shared/starboard/drm/drm_get_metrics.cc',
           '<(DEPTH)/starboard/shared/starboard/drm/drm_is_server_certificate_updatable.cc',
           '<(DEPTH)/starboard/shared/starboard/drm/drm_system_internal.h',
           '<(DEPTH)/starboard/shared/starboard/drm/drm_update_server_certificate.cc',
@@ -440,6 +447,7 @@
           '<(DEPTH)/starboard/shared/stub/drm_create_system.cc',
           '<(DEPTH)/starboard/shared/stub/drm_destroy_system.cc',
           '<(DEPTH)/starboard/shared/stub/drm_generate_session_update_request.cc',
+          '<(DEPTH)/starboard/shared/stub/drm_get_metrics.cc',
           '<(DEPTH)/starboard/shared/stub/drm_is_server_certificate_updatable.cc',
           '<(DEPTH)/starboard/shared/stub/drm_system_internal.h',
           '<(DEPTH)/starboard/shared/stub/drm_update_server_certificate.cc',
diff --git a/src/starboard/linux/shared/system_get_path.cc b/src/starboard/linux/shared/system_get_path.cc
index 06abade..3f1e7d0 100644
--- a/src/starboard/linux/shared/system_get_path.cc
+++ b/src/starboard/linux/shared/system_get_path.cc
@@ -163,6 +163,17 @@
 
   return true;
 }
+
+// Gets the path to the content directory.
+bool GetContentDirectory(char* out_path, int path_size) {
+  if (!GetExecutableDirectory(out_path, path_size)) {
+    return false;
+  }
+  if (SbStringConcat(out_path, "/content", path_size) >= path_size) {
+    return false;
+  }
+  return true;
+}
 }  // namespace
 
 bool SbSystemGetPath(SbSystemPathId path_id, char* out_path, int path_size) {
@@ -176,10 +187,7 @@
 
   switch (path_id) {
     case kSbSystemPathContentDirectory:
-      if (!GetExecutableDirectory(path.data(), kPathSize)) {
-        return false;
-      }
-      if (SbStringConcat(path.data(), "/content", kPathSize) >= kPathSize) {
+      if (!GetContentDirectory(path.data(), kPathSize)) {
         return false;
       }
 #if SB_IS(EVERGREEN_COMPATIBLE)
@@ -229,9 +237,19 @@
 
     case kSbSystemPathFontConfigurationDirectory:
     case kSbSystemPathFontDirectory:
+#if SB_IS(EVERGREEN_COMPATIBLE)
+      if (!GetContentDirectory(path.data(), kPathSize)) {
         return false;
+      }
+      if (SbStringConcat(path.data(), "/fonts", kPathSize) >= kPathSize) {
+        return false;
+      }
+      break;
+#else
+      return false;
+#endif
 
-#if SB_API_VERSION >= SB_STORAGE_PATH_VERSION
+#if SB_API_VERSION >= 12
     case kSbSystemPathStorageDirectory:
       if (!GetStorageDirectory(path.data(), kPathSize)) {
         return false;
diff --git a/src/starboard/linux/x64x11/blittergles/gyp_configuration.py b/src/starboard/linux/x64x11/blittergles/gyp_configuration.py
index 87d96c7..0df9c53 100644
--- a/src/starboard/linux/x64x11/blittergles/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/blittergles/gyp_configuration.py
@@ -22,4 +22,4 @@
 def CreatePlatformConfig():
   return parent_configuration.LinuxX64X11Configuration(
       'linux-x64x11-blittergles',
-      sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
+      sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py
index 7baf5ea..0266fbc 100644
--- a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py
@@ -33,7 +33,7 @@
   def __init__(self,
                platform,
                asan_enabled_by_default=False,
-               sabi_json_path=None):
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     super(LinuxX64X11Clang36Configuration, self).__init__(
         platform,
         asan_enabled_by_default,
@@ -72,7 +72,7 @@
     })
     return variables
 
-  def GetTargetToolchain(self):
+  def GetTargetToolchain(self, **kwargs):
     environment_variables = self.GetEnvironmentVariables()
     cc_path = environment_variables['CC']
     cxx_path = environment_variables['CXX']
@@ -90,7 +90,7 @@
         bash.Shell(),
     ]
 
-  def GetHostToolchain(self):
+  def GetHostToolchain(self, **kwargs):
     environment_variables = self.GetEnvironmentVariables()
     cc_path = environment_variables['CC_host']
     cxx_path = environment_variables['CXX_host']
@@ -113,7 +113,7 @@
   try:
     return LinuxX64X11Clang36Configuration(
         'linux-x64x11-clang-3-6',
-        sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
+        sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
   except RuntimeError as e:
     logging.critical(e)
     return None
diff --git a/src/starboard/linux/x64x11/dlmalloc/gyp_configuration.py b/src/starboard/linux/x64x11/dlmalloc/gyp_configuration.py
index ea9e459..488666a 100644
--- a/src/starboard/linux/x64x11/dlmalloc/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/dlmalloc/gyp_configuration.py
@@ -32,4 +32,4 @@
 def CreatePlatformConfig():
   return LinuxX64X11DlmallocConfiguration(
       'linux-x64x11-dlmalloc',
-      sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
+      sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/linux/x64x11/egl/gyp_configuration.py b/src/starboard/linux/x64x11/egl/gyp_configuration.py
index 5fad9bc..a617e7f 100644
--- a/src/starboard/linux/x64x11/egl/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/egl/gyp_configuration.py
@@ -18,4 +18,5 @@
 
 def CreatePlatformConfig():
   return linux_configuration.LinuxX64X11Configuration(
-      'linux-x64x11-egl', sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
+      'linux-x64x11-egl',
+      sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py b/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py
index 6d8bd71..2fbd354 100644
--- a/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py
@@ -18,6 +18,12 @@
 
 from starboard.linux.shared import gyp_configuration as shared_configuration
 from starboard.tools import build
+from starboard.tools.toolchain import ar
+from starboard.tools.toolchain import bash
+from starboard.tools.toolchain import clang
+from starboard.tools.toolchain import clangxx
+from starboard.tools.toolchain import cp
+from starboard.tools.toolchain import touch
 
 
 class LinuxX64X11Gcc63Configuration(shared_configuration.LinuxConfiguration):
@@ -26,7 +32,7 @@
   def __init__(self,
                platform,
                asan_enabled_by_default=False,
-               sabi_json_path=None):
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     super(LinuxX64X11Gcc63Configuration, self).__init__(
         platform,
         asan_enabled_by_default,
@@ -64,8 +70,44 @@
     }
     return env_variables
 
+  def GetTargetToolchain(self, **kwargs):
+    environment_variables = self.GetEnvironmentVariables()
+    cc_path = environment_variables['CC']
+    cxx_path = environment_variables['CXX']
+
+    return [
+        clang.CCompiler(path=cc_path),
+        clang.CxxCompiler(path=cxx_path),
+        clang.AssemblerWithCPreprocessor(path=cc_path),
+        ar.StaticThinLinker(),
+        ar.StaticLinker(),
+        clangxx.ExecutableLinker(path=cxx_path, write_group=True),
+        clangxx.SharedLibraryLinker(path=cxx_path),
+        cp.Copy(),
+        touch.Stamp(),
+        bash.Shell(),
+    ]
+
+  def GetHostToolchain(self, **kwargs):
+    environment_variables = self.GetEnvironmentVariables()
+    cc_path = environment_variables['CC_HOST']
+    cxx_path = environment_variables['CXX_HOST']
+
+    return [
+        clang.CCompiler(path=cc_path),
+        clang.CxxCompiler(path=cxx_path),
+        clang.AssemblerWithCPreprocessor(path=cc_path),
+        ar.StaticThinLinker(),
+        ar.StaticLinker(),
+        clangxx.ExecutableLinker(path=cxx_path, write_group=True),
+        clangxx.SharedLibraryLinker(path=cxx_path),
+        cp.Copy(),
+        touch.Stamp(),
+        bash.Shell(),
+    ]
+
 
 def CreatePlatformConfig():
   return LinuxX64X11Gcc63Configuration(
       'linux-x64x11-gcc-6-3',
-      sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
+      sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/linux/x64x11/gczeal/configuration.cc b/src/starboard/linux/x64x11/gczeal/configuration.cc
index d692d79..f39c87f 100644
--- a/src/starboard/linux/x64x11/gczeal/configuration.cc
+++ b/src/starboard/linux/x64x11/gczeal/configuration.cc
@@ -25,10 +25,14 @@
 namespace {
 
 int CobaltEglSwapInterval() {
+  // This platform uses a compositor to present the rendering output, so
+  // set the swap interval to update the buffer immediately. That buffer
+  // will then be presented by the compositor on its own time.
   return 0;
 }
 
 bool CobaltGcZeal() {
+  // Enable zealous garbage collection.
   return true;
 }
 
diff --git a/src/starboard/linux/x64x11/gczeal/gyp_configuration.gypi b/src/starboard/linux/x64x11/gczeal/gyp_configuration.gypi
index d1065b0..909c6e8 100644
--- a/src/starboard/linux/x64x11/gczeal/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/gczeal/gyp_configuration.gypi
@@ -13,10 +13,6 @@
 # limitations under the License.
 
 {
-  'variables': {
-    # Enable zealous garbage collection.
-    'cobalt_gc_zeal': 1,
-  },
   'target_defaults': {
     'default_configuration': 'linux-x64x11-gczeal_debug',
     'configurations': {
diff --git a/src/starboard/linux/x64x11/gczeal/gyp_configuration.py b/src/starboard/linux/x64x11/gczeal/gyp_configuration.py
index fff7400..128b202 100644
--- a/src/starboard/linux/x64x11/gczeal/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/gczeal/gyp_configuration.py
@@ -18,4 +18,5 @@
 
 def CreatePlatformConfig():
   return linux_configuration.LinuxX64X11Configuration(
-      'linux-x64x11-gczeal', sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
+      'linux-x64x11-gczeal',
+      sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/linux/x64x11/gyp_configuration.py b/src/starboard/linux/x64x11/gyp_configuration.py
index 6b08b17..f62c9ea 100644
--- a/src/starboard/linux/x64x11/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/gyp_configuration.py
@@ -32,17 +32,17 @@
                platform_name='linux-x64x11',
                asan_enabled_by_default=True,
                goma_supports_compiler=True,
-               sabi_json_path=None):
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     super(LinuxX64X11Configuration, self).__init__(
         platform_name,
         asan_enabled_by_default,
         goma_supports_compiler,
         sabi_json_path=sabi_json_path)
 
-  def GetTargetToolchain(self):
-    return self.GetHostToolchain()
+  def GetTargetToolchain(self, **kwargs):
+    return self.GetHostToolchain(**kwargs)
 
-  def GetHostToolchain(self):
+  def GetHostToolchain(self, **kwargs):
     environment_variables = self.GetEnvironmentVariables()
     cc_path = environment_variables['CC']
     cxx_path = environment_variables['CXX']
@@ -82,4 +82,4 @@
 
 def CreatePlatformConfig():
   return LinuxX64X11Configuration(
-      sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
+      sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/linux/x64x11/sbversion/10/configuration_public.h b/src/starboard/linux/x64x11/sbversion/10/configuration_public.h
index 4b7de4e..484c00a 100644
--- a/src/starboard/linux/x64x11/sbversion/10/configuration_public.h
+++ b/src/starboard/linux/x64x11/sbversion/10/configuration_public.h
@@ -91,4 +91,7 @@
 // Whether the current platform implements the on screen keyboard interface.
 #define SB_HAS_ON_SCREEN_KEYBOARD 0
 
+// Whether the current platform has JIT support
+#define ENGINE_SUPPORTS_JIT 1
+
 #endif  // STARBOARD_LINUX_X64X11_SBVERSION_10_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.gypi b/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.gypi
index 072dd55..28a6c72 100644
--- a/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.gypi
@@ -40,5 +40,9 @@
 
   'includes': [
     '<(DEPTH)/starboard/linux/x64x11/shared/gyp_configuration.gypi',
+    # Include the test_webapi_extension.gypi here to ensure that the
+    # webapi_extension facilities get built and tested on at least one build.
+    # See cobalt/doc/webapi_extension.md for more information.
+    '<(DEPTH)/starboard/shared/test_webapi_extension/test_webapi_extension.gypi',
   ],
 }
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/linux/x64x11/sbversion/12/atomic_public.h
similarity index 72%
rename from src/starboard/raspi/0/atomic_public.h
rename to src/starboard/linux/x64x11/sbversion/12/atomic_public.h
index 0fbc0ef..b6110e0 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/linux/x64x11/sbversion/12/atomic_public.h
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_LINUX_X64X11_SBVERSION_12_ATOMIC_PUBLIC_H_
+#define STARBOARD_LINUX_X64X11_SBVERSION_12_ATOMIC_PUBLIC_H_
 
-#include "starboard/raspi/shared/atomic_public.h"
+#include "starboard/linux/x64x11/atomic_public.h"
 
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#endif  // STARBOARD_LINUX_X64X11_SBVERSION_12_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/12/configuration_public.h b/src/starboard/linux/x64x11/sbversion/12/configuration_public.h
new file mode 100644
index 0000000..b38e6b0
--- /dev/null
+++ b/src/starboard/linux/x64x11/sbversion/12/configuration_public.h
@@ -0,0 +1,43 @@
+// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The Starboard configuration for Desktop x64 Linux. Other devices will have
+// specific Starboard implementations, even if they ultimately are running some
+// version of Linux.
+
+// Other source files should never include this header directly, but should
+// include the generic "starboard/configuration.h" instead.
+
+#ifndef STARBOARD_LINUX_X64X11_SBVERSION_12_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_LINUX_X64X11_SBVERSION_12_CONFIGURATION_PUBLIC_H_
+
+// --- Graphics Configuration ------------------------------------------------
+
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#define SB_HAS_NV12_TEXTURE_SUPPORT 1
+
+// --- Shared Configuration and Overrides ------------------------------------
+
+// Include the Linux configuration that's common between all Desktop Linuxes.
+#include "starboard/linux/shared/configuration_public.h"
+
+// Whether the current platform has speech synthesis.
+#undef SB_HAS_SPEECH_SYNTHESIS
+#define SB_HAS_SPEECH_SYNTHESIS 0
+
+// Whether the current platform implements the on screen keyboard interface.
+#define SB_HAS_ON_SCREEN_KEYBOARD 0
+
+#endif  // STARBOARD_LINUX_X64X11_SBVERSION_12_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/12/gyp_configuration.gypi b/src/starboard/linux/x64x11/sbversion/12/gyp_configuration.gypi
new file mode 100644
index 0000000..0cedf8f
--- /dev/null
+++ b/src/starboard/linux/x64x11/sbversion/12/gyp_configuration.gypi
@@ -0,0 +1,43 @@
+# Copyright 2014 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+  'variables': {
+    'variables': {
+      'sb_evergreen_compatible': 1,
+    }
+  },
+  'target_defaults': {
+    'default_configuration': 'linux-x64x11-sbversion-12_debug',
+    'configurations': {
+      'linux-x64x11-sbversion-12_debug': {
+        'inherit_from': ['debug_base'],
+      },
+      'linux-x64x11-sbversion-12_devel': {
+        'inherit_from': ['devel_base'],
+      },
+      'linux-x64x11-sbversion-12_qa': {
+        'inherit_from': ['qa_base'],
+      },
+      'linux-x64x11-sbversion-12_gold': {
+        'inherit_from': ['gold_base'],
+      },
+    }, # end of configurations
+  },
+
+  'includes': [
+    '<(DEPTH)/starboard/linux/x64x11/shared/gyp_configuration.gypi',
+    '<(DEPTH)/starboard/sabi/sabi.gypi',
+  ],
+}
diff --git a/src/starboard/stub/cobalt/configuration.gypi b/src/starboard/linux/x64x11/sbversion/12/gyp_configuration.py
similarity index 64%
rename from src/starboard/stub/cobalt/configuration.gypi
rename to src/starboard/linux/x64x11/sbversion/12/gyp_configuration.py
index 3c83fa0..6dd53b0 100644
--- a/src/starboard/stub/cobalt/configuration.gypi
+++ b/src/starboard/linux/x64x11/sbversion/12/gyp_configuration.py
@@ -11,12 +11,12 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+"""Starboard Linux X64 X11 platform configuration."""
 
-# Cobalt-on-Stub-specific configuration.
+from starboard.linux.x64x11 import gyp_configuration as parent_configuration
 
-{
-  'variables': {
-    # Use a stub rasterizer and graphical setup.
-    'rasterizer_type': 'stub',
-  },
-}
+
+def CreatePlatformConfig():
+  return parent_configuration.LinuxX64X11Configuration(
+      platform_name='linux-x64x11-sbversion-12',
+      sabi_json_path='starboard/sabi/x64/sysv/sabi-v12.json')
diff --git a/src/starboard/linux/x64x11/sbversion/12/starboard_platform.gyp b/src/starboard/linux/x64x11/sbversion/12/starboard_platform.gyp
new file mode 100644
index 0000000..a2ca957
--- /dev/null
+++ b/src/starboard/linux/x64x11/sbversion/12/starboard_platform.gyp
@@ -0,0 +1,24 @@
+# Copyright 2015 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Note, that despite the file extension ".gyp", this file is included by several
+# platform variants of linux-x64x11, like a ".gypi" file, since those platforms
+# have no need to modify this code.
+{
+  'includes': [
+    # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file.  The idea
+    # is that we just want this file to *be* the parent gyp file.
+    '<(DEPTH)/starboard/linux/x64x11/starboard_platform.gyp',
+  ],
+}
diff --git a/src/starboard/raspi/0/starboard_platform.gyp b/src/starboard/linux/x64x11/sbversion/12/starboard_platform_tests.gyp
similarity index 67%
copy from src/starboard/raspi/0/starboard_platform.gyp
copy to src/starboard/linux/x64x11/sbversion/12/starboard_platform_tests.gyp
index 021af7c..29448ac 100644
--- a/src/starboard/raspi/0/starboard_platform.gyp
+++ b/src/starboard/linux/x64x11/sbversion/12/starboard_platform_tests.gyp
@@ -1,4 +1,4 @@
-# Copyright 2017 The Cobalt Authors. All Rights Reserved.
+# Copyright 2018 The Cobalt Authors. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,6 +13,8 @@
 # limitations under the License.
 {
   'includes': [
-    '../shared/starboard_platform.gypi',
+    # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file.  The idea
+    # is that we just want this file to *be* the parent gyp file.
+    '<(DEPTH)/starboard/linux/x64x11/starboard_platform_tests.gyp',
   ],
 }
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/linux/x64x11/sbversion/12/thread_types_public.h
similarity index 70%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/linux/x64x11/sbversion/12/thread_types_public.h
index 0fbc0ef..0d4b065 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/linux/x64x11/sbversion/12/thread_types_public.h
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_LINUX_X64X11_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_LINUX_X64X11_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
 
-#include "starboard/raspi/shared/atomic_public.h"
+#include "starboard/linux/x64x11/thread_types_public.h"
 
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#endif  // STARBOARD_LINUX_X64X11_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/skia/configuration.cc b/src/starboard/linux/x64x11/skia/configuration.cc
index cc918a5..9e03006 100644
--- a/src/starboard/linux/x64x11/skia/configuration.cc
+++ b/src/starboard/linux/x64x11/skia/configuration.cc
@@ -25,13 +25,21 @@
 namespace {
 
 int CobaltEglSwapInterval() {
+  // This platform uses a compositor to present the rendering output, so
+  // set the swap interval to update the buffer immediately. That buffer
+  // will then be presented by the compositor on its own time.
   return 0;
 }
 
 const char* CobaltRasterizerType() {
+  // Use the skia hardware rasterizer.
   return "hardware";
 }
 
+bool CobaltEnableJit() {
+  return true;
+}
+
 const CobaltExtensionConfigurationApi kConfigurationApi = {
     kCobaltExtensionConfigurationName,
     1,
@@ -56,7 +64,7 @@
     &common::CobaltReduceGpuMemoryByDefault,
     &common::CobaltGcZealDefault,
     &CobaltRasterizerType,
-    &common::CobaltEnableJitDefault,
+    &CobaltEnableJit,
 };
 
 }  // namespace
diff --git a/src/starboard/linux/x64x11/skia/gyp_configuration.gypi b/src/starboard/linux/x64x11/skia/gyp_configuration.gypi
index a28438a..51a2f3a 100644
--- a/src/starboard/linux/x64x11/skia/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/skia/gyp_configuration.gypi
@@ -13,10 +13,6 @@
 # limitations under the License.
 
 {
-  'variables': {
-    # Use the skia hardware rasterizer.
-    'rasterizer_type': 'hardware',
-  },
   'target_defaults': {
     'default_configuration': 'linux-x64x11-skia_debug',
     'configurations': {
diff --git a/src/starboard/linux/x64x11/skia/gyp_configuration.py b/src/starboard/linux/x64x11/skia/gyp_configuration.py
index 206dba1..3964e75 100644
--- a/src/starboard/linux/x64x11/skia/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/skia/gyp_configuration.py
@@ -18,4 +18,5 @@
 
 def CreatePlatformConfig():
   return linux_configuration.LinuxX64X11Configuration(
-      'linux-x64x11-skia', sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
+      'linux-x64x11-skia',
+      sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/linux/x64x11/vulkan/gyp_configuration.py b/src/starboard/linux/x64x11/vulkan/gyp_configuration.py
index 037797f..64148c0 100644
--- a/src/starboard/linux/x64x11/vulkan/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/vulkan/gyp_configuration.py
@@ -18,4 +18,5 @@
 
 def CreatePlatformConfig():
   return linux_configuration.LinuxX64X11Configuration(
-      'linux-x64x11-vulkan', sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
+      'linux-x64x11-vulkan',
+      sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/loader_app/installation_manager.cc b/src/starboard/loader_app/installation_manager.cc
index b463471..35d166f 100644
--- a/src/starboard/loader_app/installation_manager.cc
+++ b/src/starboard/loader_app/installation_manager.cc
@@ -484,7 +484,7 @@
   }
   installation_store_.SerializeToArray(buf, installation_store_.ByteSize());
 
-#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#if SB_API_VERSION >= 12
   if (!SbFileAtomicReplace(store_path_.c_str(), buf,
                            installation_store_.ByteSize())) {
     SB_LOG(ERROR)
@@ -497,15 +497,14 @@
 
 #else
   SB_NOTREACHED()
-      << "SbFileAtomicReplace is not available before starboard version "
-      << SB_FILE_ATOMIC_REPLACE_VERSION;
+      << "SbFileAtomicReplace is not available before starboard version 12";
   return false;
 #endif
 }
 
 bool InstallationManager::InitInstallationStorePath() {
   std::vector<char> storage_dir(kSbFileMaxPath);
-#if SB_API_VERSION >= SB_STORAGE_PATH_VERSION
+#if SB_API_VERSION >= 12
   if (!SbSystemGetPath(kSbSystemPathStorageDirectory, storage_dir.data(),
                        kSbFileMaxPath)) {
     SB_LOG(ERROR) << "InitInstallationStorePath: Failed to get "
@@ -516,7 +515,7 @@
   SB_NOTREACHED() << "InitInstallationStorePath: kSbSystemPathStorageDirectory "
                      "is not available before "
                      "starboard version "
-                  << SB_STORAGE_PATH_VERSION;
+                  << 12;
   return false;
 
 #endif
diff --git a/src/starboard/loader_app/installation_manager.h b/src/starboard/loader_app/installation_manager.h
index 30a27fb..740d647 100644
--- a/src/starboard/loader_app/installation_manager.h
+++ b/src/starboard/loader_app/installation_manager.h
@@ -39,7 +39,7 @@
 
 // The max number a tries per installation before it
 // is discarded if not successful.
-#define IM_MAX_NUM_TRIES 5
+#define IM_MAX_NUM_TRIES 3
 
 // The Installation Manager API is thread safe and
 // can be used from any thread. Most calls would
diff --git a/src/starboard/loader_app/installation_manager_test.cc b/src/starboard/loader_app/installation_manager_test.cc
index 0d5f358..98dec2f 100644
--- a/src/starboard/loader_app/installation_manager_test.cc
+++ b/src/starboard/loader_app/installation_manager_test.cc
@@ -21,8 +21,7 @@
 #include "starboard/loader_app/installation_store.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if SB_API_VERSION >= SB_STORAGE_PATH_VERSION && \
-    SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#if SB_API_VERSION >= 12 && SB_API_VERSION >= 12
 
 #define NUMBER_INSTALLS_PARAMS ::testing::Values(2, 3, 4, 5, 6)
 
@@ -168,7 +167,7 @@
     ImUninitialize();
     SbDirectory dir = SbDirectoryOpen(storage_path_.c_str(), NULL);
     std::vector<std::string> dir_;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
     std::vector<char> dir_entry(kSbFileMaxName);
 
     while (SbDirectoryGetNext(dir, dir_entry.data(), dir_entry.size())) {
@@ -177,7 +176,7 @@
       full_path += dir_entry.data();
       SbFileDelete(full_path.c_str());
     }
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else   // SB_API_VERSION >= 12
     SbDirectoryEntry dir_entry;
 
     while (SbDirectoryGetNext(dir, &dir_entry)) {
@@ -186,7 +185,7 @@
       full_path += dir_entry.name;
       SbFileDelete(full_path.c_str());
     }
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
     SbDirectoryClose(dir);
     SbFileDelete(storage_path_.c_str());
   }
@@ -551,5 +550,5 @@
 }  // namespace loader_app
 }  // namespace starboard
 
-#endif  // SB_API_VERSION >= SB_STORAGE_PATH_VERSION && SB_API_VERSION >=
-        // SB_FILE_ATOMIC_REPLACE_VERSION
+#endif  // SB_API_VERSION >= 12 && SB_API_VERSION >=
+        // 12
diff --git a/src/starboard/loader_app/loader_app.cc b/src/starboard/loader_app/loader_app.cc
index 7091fb9..4e8abc7 100644
--- a/src/starboard/loader_app/loader_app.cc
+++ b/src/starboard/loader_app/loader_app.cc
@@ -29,7 +29,7 @@
 
 namespace {
 // The max number of installations slots.
-const int kMaxNumInstallations = 3;
+const int kMaxNumInstallations = 2;
 
 // Relative path for the Cobalt so file.
 const char kCobaltLibraryPath[] = "lib";
diff --git a/src/starboard/loader_app/loader_app.gyp b/src/starboard/loader_app/loader_app.gyp
index 097b5fa..0c2adfd 100644
--- a/src/starboard/loader_app/loader_app.gyp
+++ b/src/starboard/loader_app/loader_app.gyp
@@ -36,6 +36,7 @@
             '<@(common_loader_app_sources)',
           ],
           'dependencies': [
+            '<(DEPTH)/cobalt/content/fonts/fonts.gyp:copy_font_data',
             '<(DEPTH)/starboard/elf_loader/elf_loader.gyp:elf_loader',
             '<@(common_loader_app_dependencies)',
             # TODO: Remove this dependency once MediaSession is migrated to use CobaltExtensions.
diff --git a/src/starboard/memory.h b/src/starboard/memory.h
index 24d2b61..b250a7f 100644
--- a/src/starboard/memory.h
+++ b/src/starboard/memory.h
@@ -192,7 +192,7 @@
 SB_DEPRECATED_EXTERNAL(
     SB_EXPORT void SbMemoryFreeAligned(void* memory));
 
-#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#if SB_API_VERSION >= 12 || SB_HAS(MMAP)
 // Allocates |size_bytes| worth of physical memory pages and maps them into
 // an available virtual region. This function returns |SB_MEMORY_MAP_FAILED|
 // on failure. |NULL| is a valid return value.
@@ -232,7 +232,7 @@
 // memory that has been written to and might be executed in the future.
 SB_EXPORT void SbMemoryFlush(void* virtual_address, int64_t size_bytes);
 #endif
-#endif  // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(MMAP)
 
 // Gets the stack bounds for the current thread.
 //
diff --git a/src/starboard/microphone.h b/src/starboard/microphone.h
index b2932fe..63f4160 100644
--- a/src/starboard/microphone.h
+++ b/src/starboard/microphone.h
@@ -43,7 +43,7 @@
 #include "starboard/export.h"
 #include "starboard/types.h"
 
-#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE)
+#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE)
 
 #if SB_API_VERSION >= 9
 #define kSbMicrophoneLabelSize 256
@@ -205,7 +205,7 @@
 }  // extern "C"
 #endif
 
-#endif  // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(MICROPHONE)
 
 #endif  // STARBOARD_MICROPHONE_H_
diff --git a/src/starboard/mutex.h b/src/starboard/mutex.h
index 790087f..5fa7b40 100644
--- a/src/starboard/mutex.h
+++ b/src/starboard/mutex.h
@@ -29,7 +29,7 @@
 extern "C" {
 #endif
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
 
 // Max size of the SbMutex type.
 #define SB_MUTEX_MAX_SIZE 80
@@ -54,7 +54,7 @@
   { 0 }
 #endif
 
-#endif  // SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#endif  // SB_API_VERSION >= 12
 
 // Enumeration of possible results from acquiring a mutex.
 typedef enum SbMutexResult {
@@ -82,17 +82,17 @@
 // |out_mutex|: The handle to the newly created mutex.
 SB_EXPORT bool SbMutexCreate(SbMutex* out_mutex);
 
-#if SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#if SB_API_VERSION >= 12
 // Destroys a mutex. The return value indicates whether the destruction was
 // successful. Destroying a locked mutex results in undefined behavior.
 //
 // |mutex|: The mutex to be invalidated.
-#else   // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#else   // SB_API_VERSION >= 12
 // Destroys a mutex. The return value indicates whether the destruction was
 // successful.
 //
 // |mutex|: The mutex to be invalidated.
-#endif  // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#endif  // SB_API_VERSION >= 12
 SB_EXPORT bool SbMutexDestroy(SbMutex* mutex);
 
 // Acquires |mutex|, blocking indefinitely. The return value identifies
@@ -102,19 +102,19 @@
 // |mutex|: The mutex to be acquired.
 SB_EXPORT SbMutexResult SbMutexAcquire(SbMutex* mutex);
 
-#if SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#if SB_API_VERSION >= 12
 // Acquires |mutex|, without blocking. The return value identifies
 // the acquisition result. SbMutexes are not reentrant, so a recursive
 // acquisition has undefined behavior.
 //
 // |mutex|: The mutex to be acquired.
-#else   // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#else   // SB_API_VERSION >= 12
 // Acquires |mutex|, without blocking. The return value identifies
 // the acquisition result. SbMutexes are not reentrant, so a recursive
 // acquisition always fails.
 //
 // |mutex|: The mutex to be acquired.
-#endif  // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#endif  // SB_API_VERSION >= 12
 SB_EXPORT SbMutexResult SbMutexAcquireTry(SbMutex* mutex);
 
 // Releases |mutex| held by the current thread. The return value indicates
diff --git a/src/starboard/nplb/BUILD.gn b/src/starboard/nplb/BUILD.gn
index f5c3d47..9ed3feb 100644
--- a/src/starboard/nplb/BUILD.gn
+++ b/src/starboard/nplb/BUILD.gn
@@ -30,7 +30,7 @@
     "//starboard/common/test_main.cc",
     "//starboard/testing/fake_graphics_context_provider.cc",
     "//starboard/testing/fake_graphics_context_provider.h",
-    "accessibility_get_setting_test.cc",
+    "accessibility_test.cc",
     "align_test.cc",
     "atomic_test.cc",
     "audio_sink_create_test.cc",
diff --git a/src/starboard/nplb/accessibility_get_setting_test.cc b/src/starboard/nplb/accessibility_get_setting_test.cc
deleted file mode 100644
index 5ff077d..0000000
--- a/src/starboard/nplb/accessibility_get_setting_test.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2017 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/accessibility.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace starboard {
-namespace nplb {
-namespace {
-
-TEST(SbAccessibilityGetSettingTest, CanCallGetTextToSpeechSettings) {
-  SbAccessibilityTextToSpeechSettings settings = {0};
-  EXPECT_TRUE(SbAccessibilityGetTextToSpeechSettings(&settings));
-}
-
-TEST(SbAccessibilityGetSettingTest, CallTextToSpeechWithInvalidArgument) {
-  // |settings| should be zero-initialized.
-  SbAccessibilityTextToSpeechSettings settings = {1};
-  EXPECT_FALSE(SbAccessibilityGetTextToSpeechSettings(&settings));
-
-  // Argument should not be NULL.
-  EXPECT_FALSE(SbAccessibilityGetTextToSpeechSettings(NULL));
-}
-
-TEST(SbAccessibilityGetSettingTest, CanCallGetDisplaySettings) {
-  SbAccessibilityDisplaySettings settings = {0};
-  EXPECT_TRUE(SbAccessibilityGetDisplaySettings(&settings));
-}
-
-TEST(SbAccessibilityGetSettingTest, CallDisplayWithInvalidArgument) {
-  // |settings| should be zero-initialized.
-  SbAccessibilityDisplaySettings settings = {1};
-  EXPECT_FALSE(SbAccessibilityGetDisplaySettings(&settings));
-
-  // Argument should not be NULL.
-  EXPECT_FALSE(SbAccessibilityGetDisplaySettings(NULL));
-}
-
-}  // namespace
-}  // namespace nplb
-}  // namespace starboard
diff --git a/src/starboard/nplb/accessibility_test.cc b/src/starboard/nplb/accessibility_test.cc
new file mode 100644
index 0000000..b182b79
--- /dev/null
+++ b/src/starboard/nplb/accessibility_test.cc
@@ -0,0 +1,163 @@
+// Copyright 2017 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/accessibility.h"
+#include "starboard/memory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+TEST(SbAccessibilityTest, CanCallGetTextToSpeechSettings) {
+  SbAccessibilityTextToSpeechSettings settings = {0};
+  EXPECT_TRUE(SbAccessibilityGetTextToSpeechSettings(&settings));
+}
+
+TEST(SbAccessibilityTest, CallTextToSpeechWithInvalidArgument) {
+  // |settings| should be zero-initialized.
+  SbAccessibilityTextToSpeechSettings settings = {1};
+  EXPECT_FALSE(SbAccessibilityGetTextToSpeechSettings(&settings));
+
+  // Argument should not be NULL.
+  EXPECT_FALSE(SbAccessibilityGetTextToSpeechSettings(NULL));
+}
+
+TEST(SbAccessibilityTest, CanCallGetDisplaySettings) {
+  SbAccessibilityDisplaySettings settings = {0};
+  EXPECT_TRUE(SbAccessibilityGetDisplaySettings(&settings));
+}
+
+TEST(SbAccessibilityTest, CallDisplayWithInvalidArgument) {
+  // |settings| should be zero-initialized.
+  SbAccessibilityDisplaySettings settings = {1};
+  EXPECT_FALSE(SbAccessibilityGetDisplaySettings(&settings));
+
+  // Argument should not be NULL.
+  EXPECT_FALSE(SbAccessibilityGetDisplaySettings(NULL));
+}
+
+#if SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
+TEST(SbAccessibilityTest, CallGetCaptionSettingsWithInvalidArgument) {
+  // |settings| should be zero-initialized.
+  const int kInvalidValue = 0xFE;
+  SbAccessibilityCaptionSettings settings;
+  SbMemorySet(&settings, kInvalidValue, sizeof(settings));
+  EXPECT_FALSE(SbAccessibilityGetCaptionSettings(&settings));
+
+  // Argument should not be NULL.
+  EXPECT_FALSE(SbAccessibilityGetCaptionSettings(NULL));
+}
+
+TEST(SbAccessibilityTest, GetCaptionSettingsReturnIsValid) {
+  // |settings| should be zero-initialized.
+  SbAccessibilityCaptionSettings settings;
+  const int kValidInitialValue = 0;
+  SbMemorySet(&settings, kValidInitialValue, sizeof(settings));
+  EXPECT_TRUE(SbAccessibilityGetCaptionSettings(&settings));
+
+  if (settings.background_color_state !=
+      kSbAccessibilityCaptionStateUnsupported) {
+    EXPECT_GE(settings.background_color, kSbAccessibilityCaptionColorBlue);
+    EXPECT_LE(settings.background_color, kSbAccessibilityCaptionColorYellow);
+  }
+
+  if (settings.background_opacity_state !=
+      kSbAccessibilityCaptionStateUnsupported) {
+    EXPECT_GE(settings.background_opacity,
+              kSbAccessibilityCaptionOpacityPercentage0);
+    EXPECT_LE(settings.background_opacity,
+              kSbAccessibilityCaptionOpacityPercentage100);
+  }
+
+  if (settings.character_edge_style_state !=
+      kSbAccessibilityCaptionStateUnsupported) {
+    EXPECT_GE(settings.character_edge_style,
+              kSbAccessibilityCaptionCharacterEdgeStyleNone);
+    EXPECT_LE(settings.character_edge_style,
+              kSbAccessibilityCaptionCharacterEdgeStyleDropShadow);
+  }
+
+  if (settings.font_color_state !=
+      kSbAccessibilityCaptionStateUnsupported) {
+    EXPECT_GE(settings.font_color, kSbAccessibilityCaptionColorBlue);
+    EXPECT_LE(settings.font_color, kSbAccessibilityCaptionColorYellow);
+  }
+
+  if (settings.font_family_state !=
+      kSbAccessibilityCaptionStateUnsupported) {
+    EXPECT_GE(settings.font_family,
+              kSbAccessibilityCaptionFontFamilyCasual);
+    EXPECT_LE(settings.font_family,
+              kSbAccessibilityCaptionFontFamilySmallCapitals);
+  }
+
+  if (settings.font_opacity_state !=
+      kSbAccessibilityCaptionStateUnsupported) {
+    EXPECT_GE(settings.font_opacity,
+              kSbAccessibilityCaptionOpacityPercentage0);
+    EXPECT_LE(settings.font_opacity,
+              kSbAccessibilityCaptionOpacityPercentage100);
+  }
+
+  if (settings.font_size_state !=
+      kSbAccessibilityCaptionStateUnsupported) {
+    EXPECT_GE(settings.font_size, kSbAccessibilityCaptionFontSizePercentage25);
+    EXPECT_LE(settings.font_size, kSbAccessibilityCaptionFontSizePercentage300);
+  }
+
+  if (settings.window_color_state !=
+      kSbAccessibilityCaptionStateUnsupported) {
+    EXPECT_GE(settings.window_color, kSbAccessibilityCaptionColorBlue);
+    EXPECT_LE(settings.window_color, kSbAccessibilityCaptionColorYellow);
+  }
+
+  if (settings.window_opacity_state !=
+      kSbAccessibilityCaptionStateUnsupported) {
+    EXPECT_GE(settings.window_opacity,
+              kSbAccessibilityCaptionOpacityPercentage0);
+    EXPECT_LE(settings.window_opacity,
+              kSbAccessibilityCaptionOpacityPercentage100);
+  }
+}
+
+TEST(SbAccessibilityTest, CallSetCaptionsEnabled) {
+  SbAccessibilityCaptionSettings settings;
+  const int kValidInitialValue = 0;
+  SbMemorySet(&settings, kValidInitialValue, sizeof(settings));
+  EXPECT_TRUE(SbAccessibilityGetCaptionSettings(&settings));
+
+  if (settings.supports_is_enabled && settings.supports_set_enabled) {
+    // Try changing the enabled state.
+    EXPECT_TRUE(SbAccessibilitySetCaptionsEnabled(!settings.is_enabled));
+
+    SbAccessibilityCaptionSettings settings2;
+    SbMemorySet(&settings2, kValidInitialValue, sizeof(settings2));
+    EXPECT_TRUE(SbAccessibilityGetCaptionSettings(&settings2));
+    EXPECT_NE(settings.is_enabled, settings2.is_enabled);
+
+    // Reset the enabled state so the unit test doesn't propagate a new setting.
+    EXPECT_TRUE(SbAccessibilitySetCaptionsEnabled(settings.is_enabled));
+
+    SbAccessibilityCaptionSettings settings3;
+    SbMemorySet(&settings3, kValidInitialValue, sizeof(settings3));
+    EXPECT_TRUE(SbAccessibilityGetCaptionSettings(&settings3));
+    EXPECT_EQ(settings.is_enabled, settings3.is_enabled);
+  }
+}
+#endif  // SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
+
+}  // namespace
+}  // namespace nplb
+}  // namespace starboard
diff --git a/src/starboard/nplb/audio_sink_create_test.cc b/src/starboard/nplb/audio_sink_create_test.cc
index 194b27f..9f61744 100644
--- a/src/starboard/nplb/audio_sink_create_test.cc
+++ b/src/starboard/nplb/audio_sink_create_test.cc
@@ -35,14 +35,13 @@
   *is_eos_reached = false;
 }
 
+#if SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+void ConsumeFramesFuncStub(int frames_consumed, void* context) {}
+#else   // SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 void ConsumeFramesFuncStub(int frames_consumed,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
                            SbTime frames_consumed_at,
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-                           // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-                           void* context) {
-}
+                           void* context) {}
+#endif  // SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 
 }  // namespace
 
diff --git a/src/starboard/nplb/audio_sink_helpers.cc b/src/starboard/nplb/audio_sink_helpers.cc
index 0974749..1ddf0f9 100644
--- a/src/starboard/nplb/audio_sink_helpers.cc
+++ b/src/starboard/nplb/audio_sink_helpers.cc
@@ -211,26 +211,21 @@
   condition_variable_.Signal();
 }
 
-void AudioSinkTestEnvironment::OnConsumeFrames(
-    int frames_consumed
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-    ,
-    SbTime frames_consumed_at
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-    ) {
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING)
-  if (kSbHasAsyncAudioFramesReporting) {
-    SB_DCHECK(frames_consumed_at <= SbTimeGetMonotonicNow());
-  }
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+#if SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+void AudioSinkTestEnvironment::OnConsumeFrames(int frames_consumed) {
   ScopedLock lock(mutex_);
   frames_consumed_ += frames_consumed;
   condition_variable_.Signal();
 }
+#else   // SB_API_VERSION >= 12 ||!SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+void AudioSinkTestEnvironment::OnConsumeFrames(int frames_consumed,
+                                               SbTime frames_consumed_at) {
+  SB_DCHECK(frames_consumed_at <= SbTimeGetMonotonicNow());
+  ScopedLock lock(mutex_);
+  frames_consumed_ += frames_consumed;
+  condition_variable_.Signal();
+}
+#endif  // SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 
 // static
 void AudioSinkTestEnvironment::UpdateSourceStatusFunc(int* frames_in_buffer,
@@ -244,30 +239,25 @@
                                     is_playing, is_eos_reached);
 }
 
+#if SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 // static
-void AudioSinkTestEnvironment::ConsumeFramesFunc(
-    int frames_consumed,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-    SbTime frames_consumed_at,
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-    void* context) {
+void AudioSinkTestEnvironment::ConsumeFramesFunc(int frames_consumed,
+                                                 void* context) {
   AudioSinkTestEnvironment* environment =
       reinterpret_cast<AudioSinkTestEnvironment*>(context);
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  if (!kSbHasAsyncAudioFramesReporting)
-    frames_consumed_at = (SbTime)kSbTimeMax;
-#endif
-  environment->OnConsumeFrames(frames_consumed, frames_consumed_at);
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
   environment->OnConsumeFrames(frames_consumed);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 }
+#else   // SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+// static
+void AudioSinkTestEnvironment::ConsumeFramesFunc(int frames_consumed,
+                                                 SbTime frames_consumed_at,
+                                                 void* context) {
+  AudioSinkTestEnvironment* environment =
+      reinterpret_cast<AudioSinkTestEnvironment*>(context);
+  frames_consumed_at = SbTimeGetMonotonicNow();
+  environment->OnConsumeFrames(frames_consumed, frames_consumed_at);
+}
+#endif  // SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/nplb/audio_sink_helpers.h b/src/starboard/nplb/audio_sink_helpers.h
index 4df20db..644d21a 100644
--- a/src/starboard/nplb/audio_sink_helpers.h
+++ b/src/starboard/nplb/audio_sink_helpers.h
@@ -95,27 +95,26 @@
                             int* offset_in_frames,
                             bool* is_playing,
                             bool* is_eos_reached);
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-  void OnConsumeFrames(int frames_consumed, SbTime frames_consumed_at);
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+#if SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
   void OnConsumeFrames(int frames_consumed);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+#else   // SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+  void OnConsumeFrames(int frames_consumed, SbTime frames_consumed_at);
+#endif  // SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 
   static void UpdateSourceStatusFunc(int* frames_in_buffer,
                                      int* offset_in_frames,
                                      bool* is_playing,
                                      bool* is_eos_reached,
                                      void* context);
+
+#if SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+  static void ConsumeFramesFunc(int frames_consumed, void* context);
+#else   // SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
   static void ConsumeFramesFunc(int frames_consumed,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
                                 SbTime frames_consumed_at,
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-                                // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
                                 void* context);
+#endif  // SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+
   SbAudioSink sink_;
 
   AudioSinkTestFrameBuffers frame_buffers_;
diff --git a/src/starboard/nplb/configuration_test.cc b/src/starboard/nplb/configuration_test.cc
index 228aeed..faf74ab 100644
--- a/src/starboard/nplb/configuration_test.cc
+++ b/src/starboard/nplb/configuration_test.cc
@@ -25,7 +25,6 @@
 SB_COMPILE_ASSERT(sizeof(int32_t) < sizeof(int64_t), int32_less_than_int64);
 
 void TheUnreferencer(int unreferenced) {
-  SB_UNREFERENCED_PARAMETER(unreferenced);
 }
 
 struct PossiblyFunnySize {
diff --git a/src/starboard/nplb/cpu_features_get_test.cc b/src/starboard/nplb/cpu_features_get_test.cc
index c72a84e..3d97501 100644
--- a/src/starboard/nplb/cpu_features_get_test.cc
+++ b/src/starboard/nplb/cpu_features_get_test.cc
@@ -67,9 +67,9 @@
   EXPECT_EQ(false, features.x86.has_sse2);
   EXPECT_EQ(false, features.x86.has_tsc);
   EXPECT_EQ(false, features.x86.has_sse3);
-#if defined(SB_CPU_FEATURE_PCLMULQDQ)
+#if SB_API_VERSION >= 12
   EXPECT_EQ(false, features.x86.has_pclmulqdq);
-#endif  // defined(SB_CPU_FEATURE_PCLMULQDQ)
+#endif  // SB_API_VERSION >= 12
   EXPECT_EQ(false, features.x86.has_ssse3);
   EXPECT_EQ(false, features.x86.has_sse41);
   EXPECT_EQ(false, features.x86.has_sse42);
diff --git a/src/starboard/nplb/cryptography_create_transformer_test.cc b/src/starboard/nplb/cryptography_create_transformer_test.cc
index 1dcf280..1bf579f 100644
--- a/src/starboard/nplb/cryptography_create_transformer_test.cc
+++ b/src/starboard/nplb/cryptography_create_transformer_test.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 
@@ -51,4 +51,4 @@
 }  // namespace nplb
 }  // namespace starboard
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/nplb/cryptography_helpers.cc b/src/starboard/nplb/cryptography_helpers.cc
index c92f422..88c606e 100644
--- a/src/starboard/nplb/cryptography_helpers.cc
+++ b/src/starboard/nplb/cryptography_helpers.cc
@@ -62,7 +62,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/nplb/cryptography_helpers.h"
 
@@ -148,4 +148,4 @@
 }  // namespace nplb
 }  // namespace starboard
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/nplb/cryptography_transform_gcm_test.cc b/src/starboard/nplb/cryptography_transform_gcm_test.cc
index 081067f..f9e3616 100644
--- a/src/starboard/nplb/cryptography_transform_gcm_test.cc
+++ b/src/starboard/nplb/cryptography_transform_gcm_test.cc
@@ -64,7 +64,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 
@@ -448,4 +448,4 @@
 }  // namespace nplb
 }  // namespace starboard
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/nplb/cryptography_transform_test.cc b/src/starboard/nplb/cryptography_transform_test.cc
index 98feac6..00d4887 100644
--- a/src/starboard/nplb/cryptography_transform_test.cc
+++ b/src/starboard/nplb/cryptography_transform_test.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 
@@ -228,4 +228,4 @@
 }  // namespace nplb
 }  // namespace starboard
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/nplb/directory_can_open_test.cc b/src/starboard/nplb/directory_can_open_test.cc
index f97ef38..388142b 100644
--- a/src/starboard/nplb/directory_can_open_test.cc
+++ b/src/starboard/nplb/directory_can_open_test.cc
@@ -30,6 +30,19 @@
   EXPECT_TRUE(SbDirectoryCanOpen(path.c_str()));
 }
 
+TEST(SbDirectoryCanOpenTest, SunnyDayStaticContent) {
+  for (auto dir_path : GetFileTestsDirectoryPaths()) {
+    EXPECT_TRUE(SbDirectoryCanOpen(dir_path.c_str()))
+        << "Can't open: " << dir_path;
+  }
+}
+
+TEST(SbDirectoryCanOpenTest, FailureMissingStaticContent) {
+  std::string directory_path = GetFileTestsDataDir();
+  std::string missing_dir = directory_path + kSbFileSepChar + "missing_dir";
+  EXPECT_FALSE(SbDirectoryCanOpen(missing_dir.c_str()));
+}
+
 TEST(SbDirectoryCanOpenTest, FailureNull) {
   EXPECT_FALSE(SbDirectoryCanOpen(NULL));
 }
diff --git a/src/starboard/nplb/directory_get_next_test.cc b/src/starboard/nplb/directory_get_next_test.cc
index d1a4d74..576e50d 100644
--- a/src/starboard/nplb/directory_get_next_test.cc
+++ b/src/starboard/nplb/directory_get_next_test.cc
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <queue>
 #include <set>
 #include <string>
 
@@ -35,7 +36,7 @@
   std::string directory_name = files[0].filename();
   directory_name.resize(directory_name.find_last_of(kSbFileSepChar));
   EXPECT_TRUE(SbFileExists(directory_name.c_str()))
-      << "Directory_name is " << directory_name;
+      << "Missing directory: " << directory_name;
 
   SbFileError error = kSbFileErrorMax;
   SbDirectory directory = SbDirectoryOpen(directory_name.c_str(), &error);
@@ -49,21 +50,20 @@
   }
 
   StringSet names_to_find(names);
-  int count = 0;
   while (true) {
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
     std::vector<char> entry(kSbFileMaxName, 0);
     if (!SbDirectoryGetNext(directory, entry.data(), entry.size())) {
       break;
     }
     const char* entry_name = entry.data();
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else   // SB_API_VERSION >= 12
     SbDirectoryEntry entry = {0};
     if (!SbDirectoryGetNext(directory, &entry)) {
       break;
     }
     const char* entry_name = entry.name;
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
 
     // SbDirectoryEntry just contains the last component of the absolute path to
     // the file, but ScopedRandomFile::filename() returns the full path.
@@ -88,15 +88,91 @@
   EXPECT_TRUE(SbDirectoryClose(directory));
 }
 
+TEST(SbDirectoryGetNextTest, SunnyDayStaticContent) {
+  std::string testdata_dir = GetFileTestsDataDir();
+  EXPECT_FALSE(testdata_dir.empty());
+  EXPECT_TRUE(SbFileExists(testdata_dir.c_str()))
+      << "Missing directory: " << testdata_dir;
+
+  // Make sure all the test directories and files are found exactly once.
+  StringSet paths_to_find;
+  for (auto path : GetFileTestsDirectoryPaths()) {
+    paths_to_find.insert(path);
+  }
+  for (auto path : GetFileTestsFilePaths()) {
+    paths_to_find.insert(path);
+  }
+
+  // Breadth-first traversal of our test data.
+  std::queue<std::string> directory_queue;
+  directory_queue.push(testdata_dir);
+  while (!directory_queue.empty()) {
+    std::string path = directory_queue.front();
+    directory_queue.pop();
+
+    SbFileError error = kSbFileErrorMax;
+    SbDirectory directory = SbDirectoryOpen(path.c_str(), &error);
+    EXPECT_TRUE(SbDirectoryIsValid(directory)) << "Can't open: " << path;
+    EXPECT_EQ(kSbFileOk, error) << "Error opening: " << path;
+
+    // Iterate all entries in this directory.
+    while (true) {
+#if SB_API_VERSION >= 12
+      std::vector<char> entry(kSbFileMaxName, 0);
+      if (!SbDirectoryGetNext(directory, entry.data(), entry.size())) {
+        break;
+      }
+      std::string entry_name = entry.data();
+#else   // SB_API_VERSION >= 12
+      SbDirectoryEntry entry = {0};
+      if (!SbDirectoryGetNext(directory, &entry)) {
+        break;
+      }
+      std::string entry_name = entry.name;
+#endif  // SB_API_VERSION >= 12
+
+      // Accept and ignore '.' and '..' directories.
+      if (entry_name == "." || entry_name == "..") {
+        continue;
+      }
+
+      // Absolute path of the entry.
+      std::string entry_path = path + kSbFileSepChar + entry_name;
+
+      StringSet::iterator iterator = paths_to_find.find(entry_path);
+      if (iterator != paths_to_find.end()) {
+        paths_to_find.erase(iterator);
+      } else {
+        ADD_FAILURE() << "Unexpected entry: " << entry_path;
+      }
+
+      // Traverse into the subdirectory.
+      SbFileInfo file_info;
+      EXPECT_TRUE(SbFileGetPathInfo(entry_path.c_str(), &file_info));
+      if (file_info.is_directory) {
+        directory_queue.push(entry_path);
+      }
+    }
+
+    EXPECT_TRUE(SbDirectoryClose(directory));
+  }
+
+  // Make sure we found all of test data directories and files.
+  EXPECT_EQ(0, paths_to_find.size());
+  for (auto it = paths_to_find.begin(); it != paths_to_find.end(); ++it) {
+    ADD_FAILURE() << "Missing entry: " << *it;
+  }
+}
+
 TEST(SbDirectoryGetNextTest, FailureInvalidSbDirectory) {
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
   std::vector<char> entry(kSbFileMaxName, 0);
   EXPECT_FALSE(
       SbDirectoryGetNext(kSbDirectoryInvalid, entry.data(), entry.size()));
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else   // SB_API_VERSION >= 12
   SbDirectoryEntry entry = {0};
   EXPECT_FALSE(SbDirectoryGetNext(kSbDirectoryInvalid, &entry));
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
 }
 
 TEST(SbDirectoryGetNextTest, FailureNullEntry) {
@@ -111,42 +187,23 @@
   SbDirectory directory = SbDirectoryOpen(path.c_str(), &error);
   EXPECT_TRUE(SbDirectoryIsValid(directory));
   EXPECT_EQ(kSbFileOk, error);
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
   EXPECT_FALSE(SbDirectoryGetNext(directory, NULL, kSbFileMaxName));
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else  // SB_API_VERSION >= 12
   EXPECT_FALSE(SbDirectoryGetNext(directory, NULL));
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
   EXPECT_TRUE(SbDirectoryClose(directory));
 }
 
 TEST(SbDirectoryGetNextTest, FailureInvalidAndNull) {
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
   EXPECT_FALSE(SbDirectoryGetNext(kSbDirectoryInvalid, NULL, kSbFileMaxName));
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else   // SB_API_VERSION >= 12
   EXPECT_FALSE(SbDirectoryGetNext(kSbDirectoryInvalid, NULL));
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
 }
 
-TEST(SbDirectoryGetNextTest, FailureOnEmptyDirectory) {
-  ScopedRandomFile dir(ScopedRandomFile::kDontCreate);
-  const std::string& path = dir.filename();
-  ASSERT_TRUE(SbDirectoryCreate(path.c_str()));
-  SbFileError error = kSbFileErrorMax;
-  SbDirectory directory = SbDirectoryOpen(path.c_str(), &error);
-  ASSERT_TRUE(SbDirectoryIsValid(directory));
-  ASSERT_EQ(kSbFileOk, error);
-
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  std::vector<char> entry(kSbFileMaxName, 0);
-  EXPECT_FALSE(SbDirectoryGetNext(directory, entry.data(), entry.size()));
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  SbDirectoryEntry entry = {0};
-  EXPECT_FALSE(SbDirectoryGetNext(directory, &entry));
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  ASSERT_TRUE(SbDirectoryClose(directory));
-}
-
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
 TEST(SbDirectoryGetNextTest, FailureOnInsufficientSize) {
   ScopedRandomFile file;
   std::string directory_name = file.filename();
@@ -170,7 +227,7 @@
 
   EXPECT_TRUE(SbDirectoryClose(directory));
 }
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
 
 }  // namespace
 }  // namespace nplb
diff --git a/src/starboard/nplb/directory_open_test.cc b/src/starboard/nplb/directory_open_test.cc
index 62cefc8..0eb10be 100644
--- a/src/starboard/nplb/directory_open_test.cc
+++ b/src/starboard/nplb/directory_open_test.cc
@@ -40,6 +40,16 @@
   EXPECT_TRUE(SbDirectoryClose(directory));
 }
 
+TEST(SbDirectoryOpenTest, SunnyDayStaticContent) {
+  for (auto dir_path : GetFileTestsDirectoryPaths()) {
+    SbFileError error = kSbFileErrorMax;
+    SbDirectory directory = SbDirectoryOpen(dir_path.c_str(), &error);
+    EXPECT_TRUE(SbDirectoryIsValid(directory)) << dir_path;
+    EXPECT_EQ(kSbFileOk, error) << "Can't open: " << dir_path;
+    EXPECT_TRUE(SbDirectoryClose(directory));
+  }
+}
+
 TEST(SbDirectoryOpenTest, SunnyDayWithNullError) {
   std::string path = GetTempDir();
   EXPECT_FALSE(path.empty());
diff --git a/src/starboard/nplb/drm_get_metrics_test.cc b/src/starboard/nplb/drm_get_metrics_test.cc
new file mode 100644
index 0000000..a26dd15
--- /dev/null
+++ b/src/starboard/nplb/drm_get_metrics_test.cc
@@ -0,0 +1,63 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/drm.h"
+
+#include "starboard/common/string.h"
+#include "starboard/nplb/drm_helpers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_API_VERSION >= 12
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+TEST(SbDrmGetMetricsTest, SunnyDay) {
+  for (auto key_system : kKeySystems) {
+    SbDrmSystem drm_system = CreateDummyDrmSystem(key_system);
+    if (!SbDrmSystemIsValid(drm_system)) {
+      continue;
+    }
+    int size = -1;
+    const void* metrics = SbDrmGetMetrics(drm_system, &size);
+    if (size > 0) {
+      ASSERT_TRUE(metrics);
+    }
+    if (metrics) {
+      ASSERT_GE(size, 0);
+    }
+    SbDrmDestroySystem(drm_system);
+  }
+}
+
+TEST(SbDrmGetMetricsTest, RainyDay) {
+  int size = -1;
+  ASSERT_FALSE(SbDrmGetMetrics(kSbDrmSystemInvalid, &size));
+
+  for (auto key_system : kKeySystems) {
+    SbDrmSystem drm_system = CreateDummyDrmSystem(key_system);
+    if (!SbDrmSystemIsValid(drm_system)) {
+      continue;
+    }
+    EXPECT_EQ(SbDrmGetMetrics(drm_system, nullptr), nullptr);
+    SbDrmDestroySystem(drm_system);
+  }
+}
+
+}  // namespace
+}  // namespace nplb
+}  // namespace starboard
+
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/nplb/extern_c_test.cc b/src/starboard/nplb/extern_c_test.cc
index 63a56b1..a83394b 100644
--- a/src/starboard/nplb/extern_c_test.cc
+++ b/src/starboard/nplb/extern_c_test.cc
@@ -24,7 +24,7 @@
 #include "starboard/condition_variable.h"
 #include "starboard/configuration.h"
 #include "starboard/cpu_features.h"
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 #include "starboard/cryptography.h"
 #endif
 #include "starboard/decode_target.h"
diff --git a/src/starboard/nplb/file_atomic_replace_test.cc b/src/starboard/nplb/file_atomic_replace_test.cc
index f0c9ba4..b14b117 100644
--- a/src/starboard/nplb/file_atomic_replace_test.cc
+++ b/src/starboard/nplb/file_atomic_replace_test.cc
@@ -16,7 +16,7 @@
 #include "starboard/nplb/file_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#if SB_API_VERSION >= 12
 
 namespace starboard {
 namespace nplb {
@@ -98,4 +98,4 @@
 }  // namespace nplb
 }  // namespace starboard
 
-#endif  // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/nplb/file_can_open_test.cc b/src/starboard/nplb/file_can_open_test.cc
index a4e3c83..cdedfd0 100644
--- a/src/starboard/nplb/file_can_open_test.cc
+++ b/src/starboard/nplb/file_can_open_test.cc
@@ -52,6 +52,20 @@
   EXPECT_TRUE(result);
 }
 
+TEST(SbFileCanOpenTest, NonExistingStaticContentFileFails) {
+  std::string directory_path = GetFileTestsDataDir();
+  std::string missing_file = directory_path + kSbFileSepChar + "missing_file";
+  EXPECT_FALSE(
+      SbFileCanOpen(missing_file.c_str(), kSbFileOpenOnly | kSbFileRead));
+}
+
+TEST(SbFileCanOpenTest, ExistingStaticContentFileSucceeds) {
+  for (auto path : GetFileTestsFilePaths()) {
+    EXPECT_TRUE(SbFileCanOpen(path.c_str(), kSbFileOpenOnly | kSbFileRead))
+        << "Can't open: " << path;
+  }
+}
+
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/nplb/file_get_info_test.cc b/src/starboard/nplb/file_get_info_test.cc
index 024d257..e66c785 100644
--- a/src/starboard/nplb/file_get_info_test.cc
+++ b/src/starboard/nplb/file_get_info_test.cc
@@ -82,6 +82,23 @@
   }
 }
 
+TEST(SbFileGetInfoTest, WorksOnStaticContentFiles) {
+  for (auto filename : GetFileTestsFilePaths()) {
+    SbFile file =
+        SbFileOpen(filename.c_str(), kSbFileOpenOnly | kSbFileRead, NULL, NULL);
+    ASSERT_TRUE(SbFileIsValid(file));
+
+    SbFileInfo info = {0};
+    bool result = SbFileGetInfo(file, &info);
+    size_t content_length = GetTestFileExpectedContent(filename).length();
+    EXPECT_EQ(content_length, info.size);
+    EXPECT_FALSE(info.is_directory);
+    EXPECT_FALSE(info.is_symbolic_link);
+
+    EXPECT_TRUE(SbFileClose(file));
+  }
+}
+
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/nplb/file_get_path_info_test.cc b/src/starboard/nplb/file_get_path_info_test.cc
index 7d33757..37ccb64 100644
--- a/src/starboard/nplb/file_get_path_info_test.cc
+++ b/src/starboard/nplb/file_get_path_info_test.cc
@@ -106,6 +106,27 @@
   }
 }
 
+TEST(SbFileGetPathInfoTest, WorksOnStaticContentFiles) {
+  for (auto filename : GetFileTestsFilePaths()) {
+    SbFileInfo info = {0};
+    bool result = SbFileGetPathInfo(filename.c_str(), &info);
+    size_t content_length = GetTestFileExpectedContent(filename).length();
+    EXPECT_EQ(content_length, info.size);
+    EXPECT_FALSE(info.is_directory);
+    EXPECT_FALSE(info.is_symbolic_link);
+  }
+}
+
+TEST(SbFileGetPathInfoTest, WorksOnStaticContentDirectories) {
+  for (auto path : GetFileTestsDirectoryPaths()) {
+    SbFileInfo info = {0};
+    bool result = SbFileGetPathInfo(path.data(), &info);
+    EXPECT_LE(0, info.size);
+    EXPECT_TRUE(info.is_directory);
+    EXPECT_FALSE(info.is_symbolic_link);
+  }
+}
+
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/nplb/file_helpers.cc b/src/starboard/nplb/file_helpers.cc
index e9f7eb5..8ac08b4 100644
--- a/src/starboard/nplb/file_helpers.cc
+++ b/src/starboard/nplb/file_helpers.cc
@@ -41,6 +41,63 @@
   return path.data();
 }
 
+std::string GetFileTestsDataDir() {
+  std::vector<char> content_path(kPathSize);
+  EXPECT_TRUE(SbSystemGetPath(kSbSystemPathContentDirectory,
+                              content_path.data(), kPathSize));
+  std::string directory_path =
+      std::string(content_path.data()) + kSbFileSepChar + "test" +
+      kSbFileSepChar + "starboard" + kSbFileSepChar + "nplb" +
+      kSbFileSepChar + "file_tests";
+  SB_CHECK(SbDirectoryCanOpen(directory_path.c_str()));
+  return directory_path;
+}
+
+// Make a vector of absolute paths in our test data from a null-terminated array
+// of C-strings with the relative paths. Slashes are converted to the platform's
+// delimiter.
+std::vector<std::string> MakePathsVector(const char* files[]) {
+  std::string directory_path = GetFileTestsDataDir();
+  std::vector<std::string> paths;
+  for (int i = 0; files[i] != nullptr; i++) {
+    std::string file_path = directory_path + kSbFileSepChar + files[i];
+    std::replace(file_path.begin(), file_path.end(), '/', kSbFileSepChar);
+    paths.push_back(file_path);
+  }
+  return paths;
+}
+
+std::vector<std::string> GetFileTestsFilePaths() {
+  const char* kFiles[] = {
+    // This long file MUST be first -- SbFileSeekTest depends on it!
+    "file_with_long_name_and_contents_for_seek_testing_1234567890",
+    "file01",
+    "dir_with_files/file11",
+    "dir_with_files/file12",
+    "dir_with_only_subdir/dir_with_files/file21",
+    "dir_with_only_subdir/dir_with_files/file22",
+    nullptr
+  };
+  return MakePathsVector(kFiles);
+}
+
+std::vector<std::string> GetFileTestsDirectoryPaths() {
+  const char* kDirs[] = {
+    "dir_with_files",
+    "dir_with_only_subdir",
+    "dir_with_only_subdir/dir_with_files",
+    nullptr
+  };
+  return MakePathsVector(kDirs);
+}
+
+std::string GetTestFileExpectedContent(const std::string& path) {
+  // The test file content matches the basename of the file + a newline.
+  std::string content(path, path.find_last_of(kSbFileSepChar) + 1);
+  content += '\n';
+  return content;
+}
+
 // static
 std::string ScopedRandomFile::MakeRandomFilename() {
   std::ostringstream filename_stream;
diff --git a/src/starboard/nplb/file_helpers.h b/src/starboard/nplb/file_helpers.h
index 12f4065..8810737 100644
--- a/src/starboard/nplb/file_helpers.h
+++ b/src/starboard/nplb/file_helpers.h
@@ -16,6 +16,7 @@
 #define STARBOARD_NPLB_FILE_HELPERS_H_
 
 #include <string>
+#include <vector>
 
 #include "starboard/file.h"
 
@@ -25,6 +26,18 @@
 // Gets the temporary directory in which ScopedRandomFile places its files.
 std::string GetTempDir();
 
+// Gets the directory in which static data for files tests is stored.
+std::string GetFileTestsDataDir();
+
+// Gets the paths of files in the static data for files tests.
+std::vector<std::string> GetFileTestsFilePaths();
+
+// Gets the paths of directories in the static data for files tests.
+std::vector<std::string> GetFileTestsDirectoryPaths();
+
+// Gets the expected content in a static data test file.
+std::string GetTestFileExpectedContent(const std::string& path);
+
 // Creates a random file of the given length, and deletes it when the instance
 // falls out of scope.
 class ScopedRandomFile {
diff --git a/src/starboard/nplb/file_open_test.cc b/src/starboard/nplb/file_open_test.cc
index b0817ca..47562d8 100644
--- a/src/starboard/nplb/file_open_test.cc
+++ b/src/starboard/nplb/file_open_test.cc
@@ -145,6 +145,18 @@
   }
 }
 
+TEST(SbFileOpenTest, OpenOnlyDoesNotOpenNonExistingStaticContentFile) {
+  std::string path = GetFileTestsDataDir();
+  std::string missing_file = path + kSbFileSepChar + "missing_file";
+  bool created = true;
+  SbFileError error = kSbFileErrorMax;
+  SbFile file = SbFileOpen(missing_file.c_str(), kSbFileOpenOnly | kSbFileRead,
+                           &created, &error);
+  EXPECT_FALSE(SbFileIsValid(file));
+  EXPECT_FALSE(created);
+  EXPECT_NE(kSbFileOk, error);
+}
+
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/nplb/file_read_test.cc b/src/starboard/nplb/file_read_test.cc
index 71a9a78..f9aa51d 100644
--- a/src/starboard/nplb/file_read_test.cc
+++ b/src/starboard/nplb/file_read_test.cc
@@ -231,6 +231,66 @@
   EXPECT_TRUE(result);
 }
 
+TYPED_TEST(SbFileReadTest, ReadStaticContent) {
+  for (auto filename : GetFileTestsFilePaths()) {
+    SbFile file =
+        SbFileOpen(filename.c_str(), kSbFileOpenOnly | kSbFileRead, NULL, NULL);
+    ASSERT_TRUE(SbFileIsValid(file)) << "Can't open: " << filename;
+
+    // Create a bigger buffer than necessary, so we can test the memory around
+    // the portion given to SbFileRead.
+    const int kRealBufferLength = kBufferLength * 2;
+    char real_buffer[kRealBufferLength] = {0};
+    const int kBufferOffset = kBufferLength / 2;
+    char* buffer = real_buffer + kBufferOffset;
+
+    // Initialize to some arbitrary pattern so we can verify it later.
+    for (int i = 0; i < kRealBufferLength; ++i) {
+      real_buffer[i] = '\xCD';
+    }
+
+    // Read and check the whole file.
+    std::string content;
+    int total = 0;
+    int max = 0;
+    while (true) {
+      int bytes_read = TypeParam::Read(file, buffer, kBufferLength);
+      if (bytes_read == 0) {
+        break;
+      }
+
+      // Check that we didn't read more than the buffer size.
+      EXPECT_GE(kBufferLength, bytes_read);
+
+      // Check that we didn't get an error.
+      EXPECT_LT(0, bytes_read);
+
+      // Do some accounting to check later.
+      total += bytes_read;
+      if (bytes_read > max) {
+        max = bytes_read;
+      }
+
+      // Accumulate the content of the whole file.
+      content.append(buffer, bytes_read);
+    }
+
+    // Check that we didn't write over any other parts of the buffer.
+    for (int i = 0; i < kBufferOffset; ++i) {
+      EXPECT_EQ('\xCD', real_buffer[i]);
+    }
+
+    for (int i = kBufferOffset + max; i < kRealBufferLength; ++i) {
+      EXPECT_EQ('\xCD', real_buffer[i]);
+    }
+
+    EXPECT_EQ(GetTestFileExpectedContent(filename), content);
+
+    bool result = SbFileClose(file);
+    EXPECT_TRUE(result);
+  }
+}
+
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/nplb/file_seek_test.cc b/src/starboard/nplb/file_seek_test.cc
index 0df25be..95bbdd4 100644
--- a/src/starboard/nplb/file_seek_test.cc
+++ b/src/starboard/nplb/file_seek_test.cc
@@ -130,6 +130,108 @@
   EXPECT_TRUE(result);
 }
 
+std::string GetTestStaticContentFile() {
+  std::string filename = GetFileTestsFilePaths().front();
+  int content_length = GetTestFileExpectedContent(filename).length();
+  EXPECT_GT(content_length, 40);
+  return filename;
+}
+
+TEST(SbFileSeekTest, FromEndInStaticContentWorks) {
+  std::string filename = GetTestStaticContentFile();
+  SbFile file =
+      SbFileOpen(filename.c_str(), kSbFileOpenOnly | kSbFileRead, NULL, NULL);
+  ASSERT_TRUE(SbFileIsValid(file));
+
+  int content_length = GetTestFileExpectedContent(filename).length();
+
+  SbFileInfo info;
+  bool result = SbFileGetInfo(file, &info);
+  EXPECT_TRUE(result);
+
+  int64_t position = SbFileSeek(file, kSbFileFromEnd, 0);
+  EXPECT_EQ(info.size, position);
+
+  int64_t target = -(content_length / 6);
+  position = SbFileSeek(file, kSbFileFromEnd, target);
+  EXPECT_EQ(info.size + target, position);
+
+  position = SbFileSeek(file, kSbFileFromEnd, -info.size);
+  EXPECT_EQ(0, position);
+
+  result = SbFileClose(file);
+  EXPECT_TRUE(result);
+}
+
+TEST(SbFileSeekTest, FromCurrentInStaticContentWorks) {
+  std::string filename = GetTestStaticContentFile();
+  SbFile file =
+      SbFileOpen(filename.c_str(), kSbFileOpenOnly | kSbFileRead, NULL, NULL);
+  ASSERT_TRUE(SbFileIsValid(file));
+
+  int content_length = GetTestFileExpectedContent(filename).length();
+
+  SbFileInfo info;
+  bool result = SbFileGetInfo(file, &info);
+  EXPECT_TRUE(result);
+
+  int64_t position = SbFileSeek(file, kSbFileFromCurrent, 0);
+  EXPECT_EQ(0, position);
+
+  int64_t target = content_length / 6;
+  position = SbFileSeek(file, kSbFileFromCurrent, target);
+  EXPECT_EQ(target, position);
+
+  position = SbFileSeek(file, kSbFileFromCurrent, target);
+  EXPECT_EQ(target * 2, position);
+
+  position = SbFileSeek(file, kSbFileFromCurrent, 0);
+  EXPECT_EQ(target * 2, position);
+
+  position = SbFileSeek(file, kSbFileFromCurrent, info.size - position);
+  EXPECT_EQ(info.size, position);
+
+  position = SbFileSeek(file, kSbFileFromCurrent, -info.size);
+  EXPECT_EQ(0, position);
+
+  result = SbFileClose(file);
+  EXPECT_TRUE(result);
+}
+
+TEST(SbFileSeekTest, FromBeginInStaticContentWorks) {
+  std::string filename = GetFileTestsFilePaths().front();
+  SbFile file =
+      SbFileOpen(filename.c_str(), kSbFileOpenOnly | kSbFileRead, NULL, NULL);
+  ASSERT_TRUE(SbFileIsValid(file));
+
+  int content_length = GetTestFileExpectedContent(filename).length();
+
+  SbFileInfo info;
+  bool result = SbFileGetInfo(file, &info);
+  EXPECT_TRUE(result);
+
+  int64_t position = SbFileSeek(file, kSbFileFromBegin, 0);
+  EXPECT_EQ(0, position);
+
+  int64_t target = content_length / 6;
+  position = SbFileSeek(file, kSbFileFromBegin, target);
+  EXPECT_EQ(target, position);
+
+  target = content_length / 3;
+  position = SbFileSeek(file, kSbFileFromBegin, target);
+  EXPECT_EQ(target, position);
+
+  target = info.size - content_length / 6;
+  position = SbFileSeek(file, kSbFileFromBegin, target);
+  EXPECT_EQ(target, position);
+
+  position = SbFileSeek(file, kSbFileFromBegin, info.size);
+  EXPECT_EQ(info.size, position);
+
+  result = SbFileClose(file);
+  EXPECT_TRUE(result);
+}
+
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/nplb/flat_map_test.cc b/src/starboard/nplb/flat_map_test.cc
index 4564290..8b0d5ba 100644
--- a/src/starboard/nplb/flat_map_test.cc
+++ b/src/starboard/nplb/flat_map_test.cc
@@ -90,9 +90,8 @@
 }
 
 SbTimeMonotonic GetThreadTimeMonotonicNow() {
-#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION || \
-    SB_HAS(TIME_THREAD_NOW)
-#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION
+#if SB_API_VERSION >= 12 || SB_HAS(TIME_THREAD_NOW)
+#if SB_API_VERSION >= 12
   if (SbTimeIsTimeThreadNowSupported())
 #endif
     return SbTimeGetMonotonicThreadNow();
diff --git a/src/starboard/nplb/image_test.cc b/src/starboard/nplb/image_test.cc
new file mode 100644
index 0000000..0590e4b
--- /dev/null
+++ b/src/starboard/nplb/image_test.cc
@@ -0,0 +1,58 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Includes all headers in a C context to make sure they compile as C files.
+
+#include "starboard/image.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+const SbDecodeTargetFormat kDecodeTargetFormats[] = {
+  kSbDecodeTargetFormat1PlaneRGBA,
+  kSbDecodeTargetFormat1PlaneBGRA,
+  kSbDecodeTargetFormat2PlaneYUVNV12,
+  kSbDecodeTargetFormat3PlaneYUVI420,
+  kSbDecodeTargetFormat3Plane10BitYUVI420,
+  kSbDecodeTargetFormat1PlaneUYVY,
+  kSbDecodeTargetFormatInvalid,
+};
+
+const char* kMimeTypes[] = {
+  "image/jpeg",
+  "image/png",
+  "image/gif",
+  "application/json",
+  "image/webp",
+  "invalid",
+};
+
+// Verify SbImageIsDecodeSupported() can be called with any parameter values.
+TEST(ImageTest, IsDecodeSupported) {
+  for (size_t format = 0;
+       format < sizeof(kDecodeTargetFormats) / sizeof(kDecodeTargetFormats[0]);
+       ++format) {
+    for (size_t mime_type = 0;
+         mime_type < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]); ++mime_type) {
+      SbImageIsDecodeSupported(kMimeTypes[mime_type],
+                               kDecodeTargetFormats[format]);
+    }
+  }
+}
+
+}  // namespace.
+}  // namespace nplb.
+}  // namespace starboard.
diff --git a/src/starboard/nplb/include_all.c b/src/starboard/nplb/include_all.c
index 39216fb..50505c4e 100644
--- a/src/starboard/nplb/include_all.c
+++ b/src/starboard/nplb/include_all.c
@@ -23,7 +23,7 @@
 #include "starboard/condition_variable.h"
 #include "starboard/configuration.h"
 #include "starboard/cpu_features.h"
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 #include "starboard/cryptography.h"
 #endif
 #include "starboard/decode_target.h"
diff --git a/src/starboard/nplb/media_set_audio_write_duration_test.cc b/src/starboard/nplb/media_set_audio_write_duration_test.cc
index 77563b1..d32b029 100644
--- a/src/starboard/nplb/media_set_audio_write_duration_test.cc
+++ b/src/starboard/nplb/media_set_audio_write_duration_test.cc
@@ -18,6 +18,7 @@
 #include "starboard/common/spin_lock.h"
 #include "starboard/configuration_constants.h"
 #include "starboard/nplb/player_creation_param_helpers.h"
+#include "starboard/nplb/player_test_util.h"
 #include "starboard/player.h"
 #include "starboard/shared/starboard/media/media_support_internal.h"
 #include "starboard/shared/starboard/media/media_util.h"
@@ -37,34 +38,6 @@
 const SbTime kDuration = kSbTimeSecond / 2;
 const SbTime kSmallWaitInterval = 10 * kSbTimeMillisecond;
 
-std::string GetTestInputDirectory() {
-  std::vector<char> content_path(kSbFileMaxPath);
-  SB_CHECK(SbSystemGetPath(kSbSystemPathContentDirectory, content_path.data(),
-                           kSbFileMaxPath));
-  std::string directory_path =
-      std::string(content_path.data()) + kSbFileSepChar + "test" +
-      kSbFileSepChar + "starboard" + kSbFileSepChar + "shared" +
-      kSbFileSepChar + "starboard" + kSbFileSepChar + "player" +
-      kSbFileSepChar + "testdata";
-
-  SB_CHECK(SbDirectoryCanOpen(directory_path.c_str()))
-      << "Cannot open directory " << directory_path;
-  return directory_path;
-}
-
-static void DeallocateSampleFunc(SbPlayer player,
-                                 void* context,
-                                 const void* sample_buffer) {
-  SB_UNREFERENCED_PARAMETER(player);
-  SB_UNREFERENCED_PARAMETER(context);
-  SB_UNREFERENCED_PARAMETER(sample_buffer);
-}
-
-std::string ResolveTestFileName(const char* filename) {
-  auto ret = GetTestInputDirectory() + kSbFileSepChar + filename;
-  return ret;
-}
-
 class SbMediaSetAudioWriteDurationTest
     : public ::testing::TestWithParam<const char*> {
  public:
@@ -205,15 +178,6 @@
   optional<PendingDecoderStatus> pending_decoder_status_;
 
  private:
-  static void DummyDeallocateSampleFunc(SbPlayer player,
-                                        void* context,
-                                        const void* sample_buffer) {}
-
-  static void DummyErrorFunc(SbPlayer player,
-                             void* context,
-                             SbPlayerError error,
-                             const char* message) {}
-
   static void DecoderStatusFunc(SbPlayer player,
                                 void* context,
                                 SbMediaType type,
@@ -312,10 +276,13 @@
   for (auto filename : kFilenames) {
     VideoDmpReader dmp_reader(ResolveTestFileName(filename).c_str());
     SB_DCHECK(dmp_reader.number_of_audio_buffers() > 0);
+
+    const SbMediaAudioSampleInfo* audio_sample_info =
+        &dmp_reader.audio_sample_info();
     if (SbMediaIsAudioSupported(dmp_reader.audio_codec(),
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
                                 "",  // content_type
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif // SB_API_VERSION >= 12
                                 dmp_reader.audio_bitrate())) {
       test_params.push_back(filename);
     }
diff --git a/src/starboard/nplb/memory_map_test.cc b/src/starboard/nplb/memory_map_test.cc
index c24bb36..56d7a31 100644
--- a/src/starboard/nplb/memory_map_test.cc
+++ b/src/starboard/nplb/memory_map_test.cc
@@ -22,7 +22,7 @@
 namespace nplb {
 namespace {
 
-#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#if SB_API_VERSION >= 12 || SB_HAS(MMAP)
 const size_t kSize = kSbMemoryPageSize * 8;
 const void* kFailed = SB_MEMORY_MAP_FAILED;
 
@@ -290,7 +290,7 @@
   }
 }
 
-#endif  // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(MMAP)
 
 }  // namespace
 }  // namespace nplb
diff --git a/src/starboard/nplb/memory_reporter_test.cc b/src/starboard/nplb/memory_reporter_test.cc
index 5596514..e327035 100644
--- a/src/starboard/nplb/memory_reporter_test.cc
+++ b/src/starboard/nplb/memory_reporter_test.cc
@@ -173,7 +173,7 @@
     return cb;
   }
 
-  void ReportAlloc(const void* memory, size_t /*size*/) {
+  void ReportAlloc(const void* memory, size_t size) {
     if (!GetMemoryTrackingEnabled_ThreadLocal()) {
       return;
     }
@@ -336,7 +336,7 @@
   EXPECT_EQ_NO_TRACKING(mem_reporter()->number_allocs(), 0);
 }
 
-#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#if SB_API_VERSION >= 12 || SB_HAS(MMAP)
 // Tests the assumption that the SbMemoryMap and SbMemoryUnmap
 // will report memory allocations.
 TEST_F(MemoryReportingTest, CapturesMemMapUnmap) {
@@ -356,7 +356,7 @@
   EXPECT_EQ_NO_TRACKING(mem_chunk, mem_reporter()->last_mem_unmap());
   EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_map_mem());
 }
-#endif  // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(MMAP)
 
 // Tests the assumption that the operator new/delete will report
 // memory allocations.
diff --git a/src/starboard/nplb/microphone_close_test.cc b/src/starboard/nplb/microphone_close_test.cc
index e271bf2..5b05853 100644
--- a/src/starboard/nplb/microphone_close_test.cc
+++ b/src/starboard/nplb/microphone_close_test.cc
@@ -20,7 +20,7 @@
 namespace nplb {
 namespace {
 
-#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE)
+#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE)
 
 TEST(SbMicrophoneCloseTest, SunnyDayCloseAreCalledMultipleTimes) {
   SbMicrophoneInfo info_array[kMaxNumberOfMicrophone];
@@ -74,7 +74,7 @@
   EXPECT_FALSE(success);
 }
 
-#endif  // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(MICROPHONE)
 
 }  // namespace
diff --git a/src/starboard/nplb/microphone_create_test.cc b/src/starboard/nplb/microphone_create_test.cc
index 94813cb..2e6aaa7 100644
--- a/src/starboard/nplb/microphone_create_test.cc
+++ b/src/starboard/nplb/microphone_create_test.cc
@@ -21,7 +21,7 @@
 namespace nplb {
 namespace {
 
-#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE)
+#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE)
 
 TEST(SbMicrophoneCreateTest, SunnyDayOnlyOneMicrophone) {
   SbMicrophoneInfo info_array[kMaxNumberOfMicrophone];
@@ -183,7 +183,7 @@
   }
 }
 
-#endif  // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(MICROPHONE)
 
 }  // namespace
diff --git a/src/starboard/nplb/microphone_destroy_test.cc b/src/starboard/nplb/microphone_destroy_test.cc
index bba3006..12456ce 100644
--- a/src/starboard/nplb/microphone_destroy_test.cc
+++ b/src/starboard/nplb/microphone_destroy_test.cc
@@ -19,13 +19,13 @@
 namespace nplb {
 namespace {
 
-#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE)
+#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE)
 
 TEST(SbMicrophoneDestroyTest, DestroyInvalidMicrophone) {
   SbMicrophoneDestroy(kSbMicrophoneInvalid);
 }
 
-#endif  // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(MICROPHONE)
 
 }  // namespace
diff --git a/src/starboard/nplb/microphone_get_available_test.cc b/src/starboard/nplb/microphone_get_available_test.cc
index 13eb081..55c225d 100644
--- a/src/starboard/nplb/microphone_get_available_test.cc
+++ b/src/starboard/nplb/microphone_get_available_test.cc
@@ -20,7 +20,7 @@
 namespace nplb {
 namespace {
 
-#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE)
+#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE)
 
 TEST(SbMicrophoneGetAvailableTest, SunnyDay) {
   SbMicrophoneInfo info_array[kMaxNumberOfMicrophone];
@@ -89,7 +89,7 @@
 
 #endif  //  SB_API_VERSION >= 9
 
-#endif  // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(MICROPHONE)
 
 }  // namespace
diff --git a/src/starboard/nplb/microphone_helpers.h b/src/starboard/nplb/microphone_helpers.h
index eb683aa..807beb2 100644
--- a/src/starboard/nplb/microphone_helpers.h
+++ b/src/starboard/nplb/microphone_helpers.h
@@ -17,7 +17,7 @@
 
 #include "starboard/microphone.h"
 
-#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE)
+#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE)
 
 namespace starboard {
 namespace nplb {
@@ -27,7 +27,7 @@
 }  // namespace nplb
 }  // namespace starboard
 
-#endif  // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(MICROPHONE)
 
 #endif  // STARBOARD_NPLB_MICROPHONE_HELPERS_H_
diff --git a/src/starboard/nplb/microphone_is_sample_rate_supported_test.cc b/src/starboard/nplb/microphone_is_sample_rate_supported_test.cc
index 7fd6e8a..804bdc6 100644
--- a/src/starboard/nplb/microphone_is_sample_rate_supported_test.cc
+++ b/src/starboard/nplb/microphone_is_sample_rate_supported_test.cc
@@ -20,7 +20,7 @@
 namespace nplb {
 namespace {
 
-#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE)
+#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE)
 
 TEST(SbMicrophoneIsSampleRateSupportedTest, SunnyDay) {
   SbMicrophoneInfo info_array[kMaxNumberOfMicrophone];
@@ -50,7 +50,7 @@
                                                  kNormallyUsedSampleRateInHz));
 }
 
-#endif  // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(MICROPHONE)
 
 }  // namespace
diff --git a/src/starboard/nplb/microphone_open_test.cc b/src/starboard/nplb/microphone_open_test.cc
index 27681b1..e66d12b 100644
--- a/src/starboard/nplb/microphone_open_test.cc
+++ b/src/starboard/nplb/microphone_open_test.cc
@@ -20,7 +20,7 @@
 namespace nplb {
 namespace {
 
-#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE)
+#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE)
 
 TEST(SbMicrophoneOpenTest, SunnyDay) {
   SbMicrophoneInfo info_array[kMaxNumberOfMicrophone];
@@ -93,7 +93,7 @@
   EXPECT_FALSE(success);
 }
 
-#endif  // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(MICROPHONE)
 
 }  // namespace
diff --git a/src/starboard/nplb/microphone_read_test.cc b/src/starboard/nplb/microphone_read_test.cc
index af8b7d3..47f1ebc 100644
--- a/src/starboard/nplb/microphone_read_test.cc
+++ b/src/starboard/nplb/microphone_read_test.cc
@@ -21,7 +21,7 @@
 namespace nplb {
 namespace {
 
-#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE)
+#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE)
 
 TEST(SbMicrophoneReadTest, SunnyDay) {
   SbMicrophoneInfo info_array[kMaxNumberOfMicrophone];
@@ -236,7 +236,7 @@
   EXPECT_LT(read_bytes, 0);
 }
 
-#endif  // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(MICROPHONE)
 
 }  // namespace
diff --git a/src/starboard/nplb/mutex_acquire_try_test.cc b/src/starboard/nplb/mutex_acquire_try_test.cc
index 806f5f8..ccd7e5b 100644
--- a/src/starboard/nplb/mutex_acquire_try_test.cc
+++ b/src/starboard/nplb/mutex_acquire_try_test.cc
@@ -16,16 +16,16 @@
 #include "starboard/configuration.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#if SB_API_VERSION >= 12
 #include "starboard/nplb/thread_helpers.h"
 #include "starboard/thread.h"
-#endif  // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#endif  // SB_API_VERSION >= 12
 
 namespace starboard {
 namespace nplb {
 namespace {
 
-#if SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#if SB_API_VERSION >= 12
 struct TestContext {
   explicit TestContext(SbMutex* mutex) : was_locked_(false), mutex_(mutex) {}
   bool was_locked_;
@@ -38,7 +38,7 @@
       (SbMutexAcquireTry(context->mutex_) == kSbMutexAcquired);
   return NULL;
 }
-#endif  // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#endif  // SB_API_VERSION >= 12
 
 TEST(SbMutexAcquireTryTest, SunnyDayUncontended) {
   SbMutex mutex;
@@ -66,7 +66,7 @@
   EXPECT_EQ(result, kSbMutexAcquired);
   EXPECT_TRUE(SbMutexIsSuccess(result));
 
-#if SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#if SB_API_VERSION >= 12
   TestContext context(&mutex);
   SbThread thread =
       SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity, true,
@@ -75,11 +75,11 @@
   EXPECT_TRUE(SbThreadIsValid(thread));
   EXPECT_TRUE(SbThreadJoin(thread, NULL));
   EXPECT_FALSE(context.was_locked_);
-#else   // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#else   // SB_API_VERSION >= 12
   result = SbMutexAcquireTry(&mutex);
   EXPECT_EQ(result, kSbMutexBusy);
   EXPECT_FALSE(SbMutexIsSuccess(result));
-#endif  // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#endif  // SB_API_VERSION >= 12
 
   EXPECT_TRUE(SbMutexRelease(&mutex));
   EXPECT_TRUE(SbMutexDestroy(&mutex));
diff --git a/src/starboard/nplb/mutex_create_test.cc b/src/starboard/nplb/mutex_create_test.cc
index 1d072c9..8c11eaa 100644
--- a/src/starboard/nplb/mutex_create_test.cc
+++ b/src/starboard/nplb/mutex_create_test.cc
@@ -16,10 +16,10 @@
 #include "starboard/configuration.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
 #include "starboard/condition_variable.h"
 #include "starboard/once.h"
-#endif  // SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#endif  // SB_API_VERSION >= 12
 
 namespace starboard {
 namespace nplb {
diff --git a/src/starboard/nplb/mutex_destroy_test.cc b/src/starboard/nplb/mutex_destroy_test.cc
index 02e072d..e555b70 100644
--- a/src/starboard/nplb/mutex_destroy_test.cc
+++ b/src/starboard/nplb/mutex_destroy_test.cc
@@ -27,10 +27,10 @@
   EXPECT_TRUE(SbMutexDestroy(&mutex));
 }
 
-#if SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#if SB_API_VERSION >= 12
 // Destroying a mutex that has already been destroyed is undefined behavior
 // and cannot be tested.
-#else   // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#else   // SB_API_VERSION >= 12
 TEST(SbMutexDestroyTest, RainyDayDestroyHeld) {
   SbMutex mutex;
   EXPECT_TRUE(SbMutexCreate(&mutex));
@@ -43,7 +43,7 @@
   EXPECT_TRUE(SbMutexRelease(&mutex));
   EXPECT_TRUE(SbMutexDestroy(&mutex));
 }
-#endif  // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#endif  // SB_API_VERSION >= 12
 
 TEST(SbMutexDestroyTest, RainyDayNull) {
   EXPECT_FALSE(SbMutexDestroy(NULL));
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp
index 0f100ce..e34ed0c 100644
--- a/src/starboard/nplb/nplb.gyp
+++ b/src/starboard/nplb/nplb.gyp
@@ -39,7 +39,7 @@
         '<(DEPTH)/starboard/common/test_main.cc',
         '<(DEPTH)/starboard/testing/fake_graphics_context_provider.cc',
         '<(DEPTH)/starboard/testing/fake_graphics_context_provider.h',
-        'accessibility_get_setting_test.cc',
+        'accessibility_test.cc',
         'align_test.cc',
         'atomic_base_test.cc',
         'atomic_test.cc',
@@ -118,6 +118,7 @@
         'double_is_finite_test.cc',
         'double_is_nan_test.cc',
         'drm_create_system_test.cc',
+        'drm_get_metrics_test.cc',
         'drm_helpers.cc',
         'drm_helpers.h',
         'drm_is_server_certificate_updatable_test.cc',
@@ -140,6 +141,7 @@
         'flat_map_test.cc',
         'gles_test.cc',
         'murmurhash2_test.cc',
+        'image_test.cc',
         'include_all.c',
         'include_all_too.c',
         'key_test.cc',
@@ -186,6 +188,8 @@
         'player_creation_param_helpers.h',
         'player_get_preferred_output_mode_test.cc',
         'player_output_mode_supported_test.cc',
+        'player_test_util.cc',
+        'player_test_util.h',
         'random_helpers.cc',
         'recursive_mutex_test.cc',
         'rwlock_test.cc',
@@ -291,6 +295,7 @@
         'time_narrow_test.cc',
         'time_zone_get_current_test.cc',
         'time_zone_get_name_test.cc',
+        'ui_navigation_test.cc',
         'undefined_behavior_test.cc',
         'unsafe_math_test.cc',
         'url_player_create_test.cc',
@@ -316,6 +321,7 @@
         '<(DEPTH)/starboard/starboard.gyp:starboard',
         '<(DEPTH)/testing/gmock.gyp:gmock',
         '<(DEPTH)/testing/gtest.gyp:gtest',
+        'copy_nplb_file_tests_data',
       ],
       'conditions': [
         ['sb_evergreen != 1', {
@@ -335,6 +341,17 @@
       'includes': [ '<(DEPTH)/starboard/nplb/sabi/sabi.gypi' ],
     },
     {
+      'target_name': 'copy_nplb_file_tests_data',
+      'type': 'none',
+      'variables': {
+        'content_test_input_files': [
+          '<(DEPTH)/starboard/nplb/testdata/file_tests/',
+        ],
+        'content_test_output_subdir': 'starboard/nplb/file_tests',
+      },
+      'includes': [ '<(DEPTH)/starboard/build/copy_test_data.gypi' ],
+    },
+    {
       'target_name': 'nplb_deploy',
       'type': 'none',
       'dependencies': [
diff --git a/src/starboard/nplb/nplb_evergreen_compat_tests/checks.h b/src/starboard/nplb/nplb_evergreen_compat_tests/checks.h
index 0dbff4e..b4da041 100644
--- a/src/starboard/nplb/nplb_evergreen_compat_tests/checks.h
+++ b/src/starboard/nplb/nplb_evergreen_compat_tests/checks.h
@@ -23,13 +23,13 @@
 #error "Evergreen requires starboard version 12 or higher!"
 #endif
 
-#if SB_API_VERSION < SB_STORAGE_PATH_VERSION
+#if SB_API_VERSION < 12
 #error \
     "Evergreen requires support for the kSbSystemPathStorageDirectory" \
     " system property!"
 #endif
 
-#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#if SB_API_VERSION < 12
 #error "Evergreen requires memory mapping!"
 #endif
 
diff --git a/src/starboard/nplb/nplb_evergreen_compat_tests/sabi_test.cc b/src/starboard/nplb/nplb_evergreen_compat_tests/sabi_test.cc
index 08560cb..60b6d6e 100644
--- a/src/starboard/nplb/nplb_evergreen_compat_tests/sabi_test.cc
+++ b/src/starboard/nplb/nplb_evergreen_compat_tests/sabi_test.cc
@@ -28,6 +28,7 @@
 
 namespace {
 
+#if SB_API_VERSION == 12
 const char* kSabiJsonIdArmHardfp =
     "{\"alignment_char\":1,\"alignment_double\":8,\"alignment_float\":4,"
     "\"alignment_int\":4,\"alignment_llong\":8,\"alignment_long\":4,"
@@ -85,6 +86,67 @@
     "\"size_of_enum\":4,\"size_of_float\":4,\"size_of_int\":4,\"size_of_"
     "llong\":8,\"size_of_long\":8,\"size_of_pointer\":8,\"size_of_short\":2,"
     "\"target_arch\":\"x64\",\"target_arch_sub\":\"\",\"word_size\":64}";
+#endif  // SB_API_VERSION == 12
+
+#if SB_API_VERSION == 13
+const char* kSabiJsonIdArmHardfp =
+    "{\"alignment_char\":1,\"alignment_double\":8,\"alignment_float\":4,"
+    "\"alignment_int\":4,\"alignment_llong\":8,\"alignment_long\":4,"
+    "\"alignment_pointer\":4,\"alignment_short\":2,\"calling_convention\":"
+    "\"eabi\",\"endianness\":\"little\",\"floating_point_abi\":\"hard\","
+    "\"floating_point_fpu\":\"vfpv3\",\"sb_api_version\":13,\"signedness_of_"
+    "char\":\"signed\",\"signedness_of_enum\":\"signed\",\"size_of_char\":1,"
+    "\"size_of_double\":8,\"size_of_enum\":4,\"size_of_float\":4,\"size_of_"
+    "int\":4,\"size_of_llong\":8,\"size_of_long\":4,\"size_of_pointer\":4,"
+    "\"size_of_short\":2,\"target_arch\":\"arm\",\"target_arch_sub\":\"v7a\","
+    "\"word_size\":32}";
+
+const char* kSabiJsonIdArmSoftfp =
+    "{\"alignment_char\":1,\"alignment_double\":8,\"alignment_float\":4,"
+    "\"alignment_int\":4,\"alignment_llong\":8,\"alignment_long\":4,"
+    "\"alignment_pointer\":4,\"alignment_short\":2,\"calling_convention\":"
+    "\"eabi\",\"endianness\":\"little\",\"floating_point_abi\":\"softfp\","
+    "\"floating_point_fpu\":\"vfpv3\",\"sb_api_version\":13,\"signedness_of_"
+    "char\":\"signed\",\"signedness_of_enum\":\"signed\",\"size_of_char\":1,"
+    "\"size_of_double\":8,\"size_of_enum\":4,\"size_of_float\":4,\"size_of_"
+    "int\":4,\"size_of_llong\":8,\"size_of_long\":4,\"size_of_pointer\":4,"
+    "\"size_of_short\":2,\"target_arch\":\"arm\",\"target_arch_sub\":\"v7a\","
+    "\"word_size\":32}";
+
+const char* kSabiJsonIdArm64 =
+    "{\"alignment_char\":1,\"alignment_double\":8,\"alignment_float\":4,"
+    "\"alignment_int\":4,\"alignment_llong\":8,\"alignment_long\":8,"
+    "\"alignment_pointer\":8,\"alignment_short\":2,\"calling_convention\":"
+    "\"aarch64\",\"endianness\":\"little\",\"floating_point_abi\":\"\","
+    "\"floating_point_fpu\":\"\",\"sb_api_version\":13,\"signedness_of_char\":"
+    "\"signed\",\"signedness_of_enum\":\"signed\",\"size_of_char\":1,\"size_of_"
+    "double\":8,\"size_of_enum\":4,\"size_of_float\":4,\"size_of_int\":4,"
+    "\"size_of_llong\":8,\"size_of_long\":8,\"size_of_pointer\":8,\"size_of_"
+    "short\":2,\"target_arch\":\"arm64\",\"target_arch_sub\":\"v8a\",\"word_"
+    "size\":64}";
+
+const char* kSabiJsonIdX86 =
+    "{\"alignment_char\":1,\"alignment_double\":8,\"alignment_float\":4,"
+    "\"alignment_int\":4,\"alignment_llong\":8,\"alignment_long\":4,"
+    "\"alignment_pointer\":4,\"alignment_short\":2,\"calling_convention\":"
+    "\"sysv\",\"endianness\":\"little\",\"floating_point_abi\":\"\",\"floating_"
+    "point_fpu\":\"\",\"sb_api_version\":13,\"signedness_of_char\":\"signed\","
+    "\"signedness_of_enum\":\"signed\",\"size_of_char\":1,\"size_of_double\":8,"
+    "\"size_of_enum\":4,\"size_of_float\":4,\"size_of_int\":4,\"size_of_"
+    "llong\":8,\"size_of_long\":4,\"size_of_pointer\":4,\"size_of_short\":2,"
+    "\"target_arch\":\"x86\",\"target_arch_sub\":\"\",\"word_size\":32}";
+
+const char* kSabiJsonIdX64Sysv =
+    "{\"alignment_char\":1,\"alignment_double\":8,\"alignment_float\":4,"
+    "\"alignment_int\":4,\"alignment_llong\":8,\"alignment_long\":8,"
+    "\"alignment_pointer\":8,\"alignment_short\":2,\"calling_convention\":"
+    "\"sysv\",\"endianness\":\"little\",\"floating_point_abi\":\"\",\"floating_"
+    "point_fpu\":\"\",\"sb_api_version\":13,\"signedness_of_char\":\"signed\","
+    "\"signedness_of_enum\":\"signed\",\"size_of_char\":1,\"size_of_double\":8,"
+    "\"size_of_enum\":4,\"size_of_float\":4,\"size_of_int\":4,\"size_of_"
+    "llong\":8,\"size_of_long\":8,\"size_of_pointer\":8,\"size_of_short\":2,"
+    "\"target_arch\":\"x64\",\"target_arch_sub\":\"\",\"word_size\":64}";
+#endif  // SB_API_VERSION == 13
 
 class SabiTest : public ::testing::Test {
  protected:
@@ -105,11 +167,15 @@
       << "The platform should use one of the predefined SABI json files!"
       << std::endl
       << "Currently supported are: " << std::endl
-      << "  starboard/sabi/arm/hardfp/sabi.json" << std::endl
-      << "  starboard/sabi/arm/softfp/sabi.json" << std::endl
-      << "  starboard/sabi/arm64/sabi.json" << std::endl
-      << "  starboard/sabi/x86/sabi.json" << std::endl
-      << "  starboard/sabi/x64/sysv/sabi.json" << std::endl;
+      << "  starboard/sabi/arm/hardfp/sabi-v" << SB_API_VERSION << ".json"
+      << std::endl
+      << "  starboard/sabi/arm/softfp/sabi-v" << SB_API_VERSION << ".json"
+      << std::endl
+      << "  starboard/sabi/arm64/sabi-v" << SB_API_VERSION << ".json"
+      << std::endl
+      << "  starboard/sabi/x86/sabi-v" << SB_API_VERSION << ".json" << std::endl
+      << "  starboard/sabi/x64/sysv/sabi-v" << SB_API_VERSION << ".json"
+      << std::endl;
 }
 
 }  // namespace
diff --git a/src/starboard/nplb/nplb_evergreen_compat_tests/storage_test.cc b/src/starboard/nplb/nplb_evergreen_compat_tests/storage_test.cc
index 8ac05ac..1214d7c 100644
--- a/src/starboard/nplb/nplb_evergreen_compat_tests/storage_test.cc
+++ b/src/starboard/nplb/nplb_evergreen_compat_tests/storage_test.cc
@@ -32,7 +32,7 @@
 namespace {
 
 const char kFileName[] = "test_file.data";
-const size_t kBufSize = 128 * 1024 * 1024;  // 128 MB
+const size_t kBufSize = 96 * 1024 * 1024;  // 96 MB
 
 class StorageTest : public ::testing::Test {
  protected:
diff --git a/src/starboard/nplb/player_create_test.cc b/src/starboard/nplb/player_create_test.cc
index 294db6a..7ff2dd8 100644
--- a/src/starboard/nplb/player_create_test.cc
+++ b/src/starboard/nplb/player_create_test.cc
@@ -18,6 +18,7 @@
 #include "starboard/configuration_constants.h"
 #include "starboard/decode_target.h"
 #include "starboard/nplb/player_creation_param_helpers.h"
+#include "starboard/nplb/player_test_util.h"
 #include "starboard/player.h"
 #include "starboard/testing/fake_graphics_context_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -27,10 +28,31 @@
 namespace {
 
 using ::starboard::testing::FakeGraphicsContextProvider;
+using ::testing::Values;
 
-class SbPlayerTest : public ::testing::Test {
+class SbPlayerTest : public ::testing::TestWithParam<SbPlayerOutputMode> {
+ public:
+  SbPlayerTest() : output_mode_(GetParam()) {}
+
+  void GetCurrentFrameIfSupported(SbPlayer player) {
+    if (output_mode_ != kSbPlayerOutputModeDecodeToTexture) {
+      return;
+    }
+#if SB_HAS(GLES2)
+    fake_graphics_context_provider_.RunOnGlesContextThread([&]() {
+      ASSERT_TRUE(SbPlayerIsValid(player));
+      SbDecodeTarget frame = SbPlayerGetCurrentFrame(player);
+      if (SbDecodeTargetIsValid(frame)) {
+        SbDecodeTargetRelease(frame);
+      }
+    });
+#endif  // SB_HAS(GLES2)
+  }
+
  protected:
   FakeGraphicsContextProvider fake_graphics_context_provider_;
+
+  SbPlayerOutputMode output_mode_;
 };
 
 void DummyDeallocateSampleFunc(SbPlayer player,
@@ -53,250 +75,136 @@
                     SbPlayerError error,
                     const char* message) {}
 
-SbPlayer CallSbPlayerCreate(
-    SbWindow window,
-    SbMediaVideoCodec video_codec,
-    SbMediaAudioCodec audio_codec,
-    SbDrmSystem drm_system,
-    const SbMediaAudioSampleInfo* audio_sample_info,
-    const char* max_video_capabilities,
-    SbPlayerDeallocateSampleFunc sample_deallocate_func,
-    SbPlayerDecoderStatusFunc decoder_status_func,
-    SbPlayerStatusFunc player_status_func,
-    void* context,
-    SbPlayerOutputMode output_mode,
-    SbDecodeTargetGraphicsContextProvider* context_provider) {
-#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-
-  if (audio_sample_info) {
-    SB_CHECK(audio_sample_info->codec == audio_codec);
-  } else {
-    SB_CHECK(audio_codec == kSbMediaAudioCodecNone);
-  }
-
-  SbPlayerCreationParam creation_param =
-      CreatePlayerCreationParam(audio_codec, video_codec);
-  if (audio_sample_info) {
-    creation_param.audio_sample_info = *audio_sample_info;
-  }
-  creation_param.drm_system = drm_system;
-  creation_param.output_mode = output_mode;
-  creation_param.video_sample_info.max_video_capabilities =
-      max_video_capabilities;
-
-  return SbPlayerCreate(window, &creation_param, sample_deallocate_func,
-                        decoder_status_func, player_status_func, DummyErrorFunc,
-                        context, context_provider);
-
-#else  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-
-  return SbPlayerCreate(window, video_codec, audio_codec,
-                        kSbDrmSystemInvalid, audio_sample_info,
-#if SB_API_VERSION >= 11
-                        max_video_capabilities,
-#endif  // SB_API_VERSION >= 11
-                        sample_deallocate_func, decoder_status_func,
-                        player_status_func,
-                        DummyErrorFunc,
-                        context, output_mode, context_provider);
-
-#endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-}
-
-bool IsOutputModeSupported(SbPlayerOutputMode output_mode,
-                           SbMediaVideoCodec codec) {
-#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-  SbPlayerCreationParam creation_param =
-      CreatePlayerCreationParam(kSbMediaAudioCodecNone, codec);
-  creation_param.output_mode = output_mode;
-  return SbPlayerGetPreferredOutputMode(&creation_param) == output_mode;
-#else   // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-  return SbPlayerOutputModeSupported(output_mode, codec, kSbDrmSystemInvalid);
-#endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-}
-
-TEST_F(SbPlayerTest, SunnyDay) {
+TEST_P(SbPlayerTest, SunnyDay) {
   SbMediaAudioSampleInfo audio_sample_info =
       CreateAudioSampleInfo(kSbMediaAudioCodecAac);
   SbMediaVideoCodec kVideoCodec = kSbMediaVideoCodecH264;
 
-  SbPlayerOutputMode output_modes[] = {kSbPlayerOutputModeDecodeToTexture,
-                                       kSbPlayerOutputModePunchOut};
+  if (!IsOutputModeSupported(output_mode_, kVideoCodec)) {
+    return;
+  }
 
-  for (int i = 0; i < SB_ARRAY_SIZE_INT(output_modes); ++i) {
-    SbPlayerOutputMode output_mode = output_modes[i];
+  SbPlayer player = CallSbPlayerCreate(
+      fake_graphics_context_provider_.window(), kSbMediaVideoCodecH264,
+      kSbMediaAudioCodecAac, kSbDrmSystemInvalid, &audio_sample_info,
+      "" /* max_video_capabilities */, DummyDeallocateSampleFunc,
+      DummyDecoderStatusFunc, DummyStatusFunc, DummyErrorFunc,
+      NULL /* context */, output_mode_,
+      fake_graphics_context_provider_.decoder_target_provider());
+  EXPECT_TRUE(SbPlayerIsValid(player));
 
-    if (!IsOutputModeSupported(output_mode, kVideoCodec)) {
-      continue;
-    }
+  GetCurrentFrameIfSupported(player);
+
+  SbPlayerDestroy(player);
+}
+
+TEST_P(SbPlayerTest, NullCallbacks) {
+  SbMediaAudioSampleInfo audio_sample_info =
+      CreateAudioSampleInfo(kSbMediaAudioCodecAac);
+  SbMediaVideoCodec kVideoCodec = kSbMediaVideoCodecH264;
+
+  if (!IsOutputModeSupported(output_mode_, kVideoCodec)) {
+    return;
+  }
+
+  {
+    SbPlayer player = CallSbPlayerCreate(
+        fake_graphics_context_provider_.window(), kSbMediaVideoCodecH264,
+        kSbMediaAudioCodecAac, kSbDrmSystemInvalid, &audio_sample_info,
+        "" /* max_video_capabilities */, NULL /* deallocate_sample_func */,
+        DummyDecoderStatusFunc, DummyStatusFunc, DummyErrorFunc,
+        NULL /* context */, output_mode_,
+        fake_graphics_context_provider_.decoder_target_provider());
+    EXPECT_FALSE(SbPlayerIsValid(player));
+
+    SbPlayerDestroy(player);
+  }
+
+  {
     SbPlayer player = CallSbPlayerCreate(
         fake_graphics_context_provider_.window(), kSbMediaVideoCodecH264,
         kSbMediaAudioCodecAac, kSbDrmSystemInvalid, &audio_sample_info,
         "" /* max_video_capabilities */, DummyDeallocateSampleFunc,
-        DummyDecoderStatusFunc, DummyStatusFunc, NULL /* context */,
-        output_mode, fake_graphics_context_provider_.decoder_target_provider());
-    EXPECT_TRUE(SbPlayerIsValid(player));
-
-    if (output_mode == kSbPlayerOutputModeDecodeToTexture) {
-      SbDecodeTarget current_frame = SbPlayerGetCurrentFrame(player);
-    }
-
-    SbPlayerDestroy(player);
-  }
-}
-
-TEST_F(SbPlayerTest, NullCallbacks) {
-  SbMediaAudioSampleInfo audio_sample_info =
-      CreateAudioSampleInfo(kSbMediaAudioCodecAac);
-  SbMediaVideoCodec kVideoCodec = kSbMediaVideoCodecH264;
-
-  SbPlayerOutputMode output_modes[] = {kSbPlayerOutputModeDecodeToTexture,
-                                       kSbPlayerOutputModePunchOut};
-
-  for (int i = 0; i < SB_ARRAY_SIZE_INT(output_modes); ++i) {
-    SbPlayerOutputMode output_mode = output_modes[i];
-    if (!IsOutputModeSupported(output_mode, kVideoCodec)) {
-      continue;
-    }
-
-    {
-      SbPlayer player = CallSbPlayerCreate(
-          fake_graphics_context_provider_.window(), kSbMediaVideoCodecH264,
-          kSbMediaAudioCodecAac, kSbDrmSystemInvalid, &audio_sample_info,
-          "" /* max_video_capabilities */, NULL /* deallocate_sample_func */,
-          DummyDecoderStatusFunc, DummyStatusFunc, NULL /* context */,
-          output_mode,
-          fake_graphics_context_provider_.decoder_target_provider());
-      EXPECT_FALSE(SbPlayerIsValid(player));
-
-      SbPlayerDestroy(player);
-    }
-
-    {
-      SbPlayer player = CallSbPlayerCreate(
-          fake_graphics_context_provider_.window(), kSbMediaVideoCodecH264,
-          kSbMediaAudioCodecAac, kSbDrmSystemInvalid, &audio_sample_info,
-          "" /* max_video_capabilities */, DummyDeallocateSampleFunc,
-          NULL /* decoder_status_func */, DummyStatusFunc, NULL /* context */,
-          output_mode,
-          fake_graphics_context_provider_.decoder_target_provider());
-      EXPECT_FALSE(SbPlayerIsValid(player));
-
-      SbPlayerDestroy(player);
-    }
-
-    {
-      SbPlayer player = CallSbPlayerCreate(
-          fake_graphics_context_provider_.window(), kSbMediaVideoCodecH264,
-          kSbMediaAudioCodecAac, kSbDrmSystemInvalid, &audio_sample_info,
-          "" /* max_video_capabilities */, DummyDeallocateSampleFunc,
-          DummyDecoderStatusFunc, NULL /*status_func */, NULL /* context */,
-          output_mode,
-          fake_graphics_context_provider_.decoder_target_provider());
-      EXPECT_FALSE(SbPlayerIsValid(player));
-
-      SbPlayerDestroy(player);
-    }
-
-#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-
-    {
-      SbPlayerCreationParam creation_param = CreatePlayerCreationParam(
-          kSbMediaAudioCodecAac, kSbMediaVideoCodecH264);
-
-      SbPlayer player = SbPlayerCreate(
-          fake_graphics_context_provider_.window(), &creation_param,
-          DummyDeallocateSampleFunc, DummyDecoderStatusFunc, DummyStatusFunc,
-          NULL /* error_func */, NULL /* context */,
-          fake_graphics_context_provider_.decoder_target_provider());
-      EXPECT_FALSE(SbPlayerIsValid(player));
-
-      SbPlayerDestroy(player);
-    }
-
-#else  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-
-    {
-      SbPlayer player = SbPlayerCreate(
-          fake_graphics_context_provider_.window(), kSbMediaVideoCodecH264,
-          kSbMediaAudioCodecAac,
-          kSbDrmSystemInvalid, &audio_sample_info,
-#if SB_API_VERSION >= 11
-          NULL /* max_video_capabilities */,
-#endif  // SB_API_VERSION >= 11
-          DummyDeallocateSampleFunc, DummyDecoderStatusFunc, DummyStatusFunc,
-          NULL /*error_func */, NULL /* context */, output_mode,
-          fake_graphics_context_provider_.decoder_target_provider());
-      EXPECT_FALSE(SbPlayerIsValid(player));
-
-      SbPlayerDestroy(player);
-    }
-
-#endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-  }
-}
-
-TEST_F(SbPlayerTest, Audioless) {
-  SbMediaVideoCodec kVideoCodec = kSbMediaVideoCodecH264;
-
-  SbPlayerOutputMode output_modes[] = {kSbPlayerOutputModeDecodeToTexture,
-                                       kSbPlayerOutputModePunchOut};
-
-  for (int i = 0; i < SB_ARRAY_SIZE_INT(output_modes); ++i) {
-    SbPlayerOutputMode output_mode = output_modes[i];
-    if (!IsOutputModeSupported(output_mode, kVideoCodec)) {
-      continue;
-    }
-
-    SbPlayer player = CallSbPlayerCreate(
-        fake_graphics_context_provider_.window(), kVideoCodec,
-        kSbMediaAudioCodecNone, kSbDrmSystemInvalid,
-        NULL /* audio_sample_info */, "" /* max_video_capabilities */,
-        DummyDeallocateSampleFunc, DummyDecoderStatusFunc, DummyStatusFunc,
-        NULL /* context */, output_mode,
+        NULL /* decoder_status_func */, DummyStatusFunc, DummyErrorFunc,
+        NULL /* context */, output_mode_,
         fake_graphics_context_provider_.decoder_target_provider());
-    EXPECT_TRUE(SbPlayerIsValid(player));
+    EXPECT_FALSE(SbPlayerIsValid(player));
 
-    if (output_mode == kSbPlayerOutputModeDecodeToTexture) {
-      SbDecodeTarget current_frame = SbPlayerGetCurrentFrame(player);
-    }
+    SbPlayerDestroy(player);
+  }
+
+  {
+    SbPlayer player = CallSbPlayerCreate(
+        fake_graphics_context_provider_.window(), kSbMediaVideoCodecH264,
+        kSbMediaAudioCodecAac, kSbDrmSystemInvalid, &audio_sample_info,
+        "" /* max_video_capabilities */, DummyDeallocateSampleFunc,
+        DummyDecoderStatusFunc, NULL /*status_func */, DummyErrorFunc,
+        NULL /* context */, output_mode_,
+        fake_graphics_context_provider_.decoder_target_provider());
+    EXPECT_FALSE(SbPlayerIsValid(player));
+
+    SbPlayerDestroy(player);
+  }
+
+  {
+    SbPlayer player = CallSbPlayerCreate(
+        fake_graphics_context_provider_.window(), kSbMediaVideoCodecH264,
+        kSbMediaAudioCodecAac, kSbDrmSystemInvalid, &audio_sample_info, "",
+        DummyDeallocateSampleFunc, DummyDecoderStatusFunc, DummyStatusFunc,
+        NULL /* error_func */, NULL /* context */, output_mode_,
+        fake_graphics_context_provider_.decoder_target_provider());
+    EXPECT_FALSE(SbPlayerIsValid(player));
 
     SbPlayerDestroy(player);
   }
 }
 
-TEST_F(SbPlayerTest, AudioOnly) {
+TEST_P(SbPlayerTest, Audioless) {
+  SbMediaVideoCodec kVideoCodec = kSbMediaVideoCodecH264;
+
+  if (!IsOutputModeSupported(output_mode_, kVideoCodec)) {
+    return;
+  }
+
+  SbPlayer player = CallSbPlayerCreate(
+      fake_graphics_context_provider_.window(), kVideoCodec,
+      kSbMediaAudioCodecNone, kSbDrmSystemInvalid, NULL /* audio_sample_info */,
+      "" /* max_video_capabilities */, DummyDeallocateSampleFunc,
+      DummyDecoderStatusFunc, DummyStatusFunc, DummyErrorFunc,
+      NULL /* context */, output_mode_,
+      fake_graphics_context_provider_.decoder_target_provider());
+  EXPECT_TRUE(SbPlayerIsValid(player));
+
+  GetCurrentFrameIfSupported(player);
+
+  SbPlayerDestroy(player);
+}
+
+TEST_P(SbPlayerTest, AudioOnly) {
   SbMediaAudioSampleInfo audio_sample_info =
       CreateAudioSampleInfo(kSbMediaAudioCodecAac);
   SbMediaAudioCodec kAudioCodec = kSbMediaAudioCodecAac;
   SbMediaVideoCodec kVideoCodec = kSbMediaVideoCodecH264;
 
-  SbPlayerOutputMode output_modes[] = {kSbPlayerOutputModeDecodeToTexture,
-                                       kSbPlayerOutputModePunchOut};
-
-  for (int i = 0; i < SB_ARRAY_SIZE_INT(output_modes); ++i) {
-    SbPlayerOutputMode output_mode = output_modes[i];
-    if (!IsOutputModeSupported(output_mode, kVideoCodec)) {
-      continue;
-    }
-
-    SbPlayer player = CallSbPlayerCreate(
-        fake_graphics_context_provider_.window(), kSbMediaVideoCodecNone,
-        kAudioCodec, kSbDrmSystemInvalid, &audio_sample_info,
-        "" /* max_video_capabilities */, DummyDeallocateSampleFunc,
-        DummyDecoderStatusFunc, DummyStatusFunc, NULL /* context */,
-        output_mode, fake_graphics_context_provider_.decoder_target_provider());
-    EXPECT_TRUE(SbPlayerIsValid(player));
-
-    if (output_mode == kSbPlayerOutputModeDecodeToTexture) {
-      SbDecodeTarget current_frame = SbPlayerGetCurrentFrame(player);
-    }
-
-    SbPlayerDestroy(player);
+  if (!IsOutputModeSupported(output_mode_, kVideoCodec)) {
+    return;
   }
+
+  SbPlayer player = CallSbPlayerCreate(
+      fake_graphics_context_provider_.window(), kSbMediaVideoCodecNone,
+      kAudioCodec, kSbDrmSystemInvalid, &audio_sample_info,
+      "" /* max_video_capabilities */, DummyDeallocateSampleFunc,
+      DummyDecoderStatusFunc, DummyStatusFunc, DummyErrorFunc,
+      NULL /* context */, output_mode_,
+      fake_graphics_context_provider_.decoder_target_provider());
+  EXPECT_TRUE(SbPlayerIsValid(player));
+
+  GetCurrentFrameIfSupported(player);
+
+  SbPlayerDestroy(player);
 }
 
-TEST_F(SbPlayerTest, MultiPlayer) {
+TEST_P(SbPlayerTest, MultiPlayer) {
   SbMediaAudioSampleInfo audio_sample_info =
       CreateAudioSampleInfo(kSbMediaAudioCodecAac);
   SbDrmSystem kDrmSystem = kSbDrmSystemInvalid;
@@ -378,8 +286,8 @@
               fake_graphics_context_provider_.window(), kVideoCodecs[l],
               kAudioCodecs[k], kSbDrmSystemInvalid, &audio_sample_info,
               "" /* max_video_capabilities */, DummyDeallocateSampleFunc,
-              DummyDecoderStatusFunc, DummyStatusFunc, NULL /* context */,
-              kOutputModes[j],
+              DummyDecoderStatusFunc, DummyStatusFunc, DummyErrorFunc,
+              NULL /* context */, kOutputModes[j],
               fake_graphics_context_provider_.decoder_target_provider()));
           if (!SbPlayerIsValid(created_players.back())) {
             created_players.pop_back();
@@ -398,6 +306,11 @@
   }
 }
 
+INSTANTIATE_TEST_CASE_P(SbPlayerTests,
+                        SbPlayerTest,
+                        Values(kSbPlayerOutputModeDecodeToTexture,
+                               kSbPlayerOutputModePunchOut));
+
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/nplb/player_test_util.cc b/src/starboard/nplb/player_test_util.cc
new file mode 100644
index 0000000..88f8233
--- /dev/null
+++ b/src/starboard/nplb/player_test_util.cc
@@ -0,0 +1,120 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/nplb/player_test_util.h"
+
+#include "starboard/directory.h"
+#include "starboard/nplb/player_creation_param_helpers.h"
+
+namespace starboard {
+namespace nplb {
+
+std::string ResolveTestFileName(const char* filename) {
+  std::vector<char> content_path(kSbFileMaxPath);
+  SB_CHECK(SbSystemGetPath(kSbSystemPathContentDirectory, content_path.data(),
+                           kSbFileMaxPath));
+  std::string directory_path = std::string(content_path.data()) +
+                               kSbFileSepChar + "test" + kSbFileSepChar +
+                               "starboard" + kSbFileSepChar + "shared" +
+                               kSbFileSepChar + "starboard" + kSbFileSepChar +
+                               "player" + kSbFileSepChar + "testdata";
+
+  SB_CHECK(SbDirectoryCanOpen(directory_path.c_str()))
+      << "Cannot open directory " << directory_path;
+  return directory_path + kSbFileSepChar + filename;
+}
+
+void DummyDeallocateSampleFunc(SbPlayer player,
+                               void* context,
+                               const void* sample_buffer) {}
+
+void DummyDecoderStatusFunc(SbPlayer player,
+                            void* context,
+                            SbMediaType type,
+                            SbPlayerDecoderState state,
+                            int ticket) {}
+
+void DummyStatusFunc(SbPlayer player,
+                     void* context,
+                     SbPlayerState state,
+                     int ticket) {}
+
+void DummyErrorFunc(SbPlayer player,
+                    void* context,
+                    SbPlayerError error,
+                    const char* message) {}
+
+SbPlayer CallSbPlayerCreate(
+    SbWindow window,
+    SbMediaVideoCodec video_codec,
+    SbMediaAudioCodec audio_codec,
+    SbDrmSystem drm_system,
+    const SbMediaAudioSampleInfo* audio_sample_info,
+    const char* max_video_capabilities,
+    SbPlayerDeallocateSampleFunc sample_deallocate_func,
+    SbPlayerDecoderStatusFunc decoder_status_func,
+    SbPlayerStatusFunc player_status_func,
+    SbPlayerErrorFunc player_error_func,
+    void* context,
+    SbPlayerOutputMode output_mode,
+    SbDecodeTargetGraphicsContextProvider* context_provider) {
+#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+
+  if (audio_sample_info) {
+    SB_CHECK(audio_sample_info->codec == audio_codec);
+  } else {
+    SB_CHECK(audio_codec == kSbMediaAudioCodecNone);
+  }
+
+  SbPlayerCreationParam creation_param =
+      nplb::CreatePlayerCreationParam(audio_codec, video_codec);
+  if (audio_sample_info) {
+    creation_param.audio_sample_info = *audio_sample_info;
+  }
+  creation_param.drm_system = drm_system;
+  creation_param.output_mode = output_mode;
+  creation_param.video_sample_info.max_video_capabilities =
+      max_video_capabilities;
+
+  return SbPlayerCreate(window, &creation_param, sample_deallocate_func,
+                        decoder_status_func, player_status_func,
+                        player_error_func, context, context_provider);
+
+#else  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+
+  return SbPlayerCreate(
+      window, video_codec, audio_codec, kSbDrmSystemInvalid, audio_sample_info,
+#if SB_API_VERSION >= 11
+      max_video_capabilities,
+#endif  // SB_API_VERSION >= 11
+      sample_deallocate_func, decoder_status_func, player_status_func,
+      player_error_func, context, output_mode, context_provider);
+
+#endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+}
+
+bool IsOutputModeSupported(SbPlayerOutputMode output_mode,
+                           SbMediaVideoCodec codec) {
+#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+  SbPlayerCreationParam creation_param =
+      CreatePlayerCreationParam(kSbMediaAudioCodecNone, codec);
+  creation_param.output_mode = output_mode;
+  return SbPlayerGetPreferredOutputMode(&creation_param) == output_mode;
+#else   // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+  return SbPlayerOutputModeSupported(output_mode, codec, kSbDrmSystemInvalid);
+#endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+}
+
+}  // namespace nplb
+}  // namespace starboard
diff --git a/src/starboard/nplb/player_test_util.h b/src/starboard/nplb/player_test_util.h
new file mode 100644
index 0000000..335e414
--- /dev/null
+++ b/src/starboard/nplb/player_test_util.h
@@ -0,0 +1,70 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_NPLB_PLAYER_TEST_UTIL_H_
+#define STARBOARD_NPLB_PLAYER_TEST_UTIL_H_
+
+#include <string>
+#include <vector>
+
+#include "starboard/configuration_constants.h"
+#include "starboard/player.h"
+
+namespace starboard {
+namespace nplb {
+
+std::string ResolveTestFileName(const char* filename);
+
+void DummyDeallocateSampleFunc(SbPlayer player,
+                               void* context,
+                               const void* sample_buffer);
+
+void DummyDecoderStatusFunc(SbPlayer player,
+                            void* context,
+                            SbMediaType type,
+                            SbPlayerDecoderState state,
+                            int ticket);
+
+void DummyPlayerStatusFunc(SbPlayer player,
+                           void* context,
+                           SbPlayerState state,
+                           int ticket);
+
+void DummyErrorFunc(SbPlayer player,
+                    void* context,
+                    SbPlayerError error,
+                    const char* message);
+
+SbPlayer CallSbPlayerCreate(
+    SbWindow window,
+    SbMediaVideoCodec video_codec,
+    SbMediaAudioCodec audio_codec,
+    SbDrmSystem drm_system,
+    const SbMediaAudioSampleInfo* audio_sample_info,
+    const char* max_video_capabilities,
+    SbPlayerDeallocateSampleFunc sample_deallocate_func,
+    SbPlayerDecoderStatusFunc decoder_status_func,
+    SbPlayerStatusFunc player_status_func,
+    SbPlayerErrorFunc player_error_func,
+    void* context,
+    SbPlayerOutputMode output_mode,
+    SbDecodeTargetGraphicsContextProvider* context_provider);
+
+bool IsOutputModeSupported(SbPlayerOutputMode output_mode,
+                           SbMediaVideoCodec codec);
+
+}  // namespace nplb
+}  // namespace starboard
+
+#endif  // STARBOARD_NPLB_PLAYER_TEST_UTIL_H_
diff --git a/src/starboard/nplb/rwlock_test.cc b/src/starboard/nplb/rwlock_test.cc
index 72ba553..baea46d 100644
--- a/src/starboard/nplb/rwlock_test.cc
+++ b/src/starboard/nplb/rwlock_test.cc
@@ -157,7 +157,6 @@
 
   void Run() override {
     SbThread current_thread = SbThreadGetCurrent();
-    SB_UNREFERENCED_PARAMETER(current_thread);
 
     for (int32_t i = begin_value_; i < end_value_; ++i) {
       DoReadAll();
diff --git a/src/starboard/nplb/sabi/alignment_test.cc b/src/starboard/nplb/sabi/alignment_test.cc
index 59060f9..d438d2e 100644
--- a/src/starboard/nplb/sabi/alignment_test.cc
+++ b/src/starboard/nplb/sabi/alignment_test.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION >= SB_SABI_FILE_VERSION
+#if SB_API_VERSION >= 12
 
 namespace starboard {
 namespace sabi {
@@ -48,4 +48,4 @@
 }  // namespace sabi
 }  // namespace starboard
 
-#endif  // SB_API_VERSION >= SB_SABI_FILE_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/nplb/sabi/endianness_test.cc b/src/starboard/nplb/sabi/endianness_test.cc
index f1ce27e..59e692c 100644
--- a/src/starboard/nplb/sabi/endianness_test.cc
+++ b/src/starboard/nplb/sabi/endianness_test.cc
@@ -15,7 +15,7 @@
 #include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if SB_API_VERSION >= SB_SABI_FILE_VERSION
+#if SB_API_VERSION >= 12
 
 namespace starboard {
 namespace sabi {
@@ -40,4 +40,4 @@
 }  // namespace sabi
 }  // namespace starboard
 
-#endif  // SB_API_VERSION >= SB_SABI_FILE_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/nplb/sabi/signedness_and_size_of_enum_test.cc b/src/starboard/nplb/sabi/signedness_and_size_of_enum_test.cc
index bf66cd8..dc23761 100644
--- a/src/starboard/nplb/sabi/signedness_and_size_of_enum_test.cc
+++ b/src/starboard/nplb/sabi/signedness_and_size_of_enum_test.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION >= SB_SABI_FILE_VERSION
+#if SB_API_VERSION >= 12
 
 namespace starboard {
 namespace sabi {
@@ -34,4 +34,4 @@
 }  // namespace sabi
 }  // namespace starboard
 
-#endif  // SB_API_VERSION >= SB_SABI_FILE_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/nplb/sabi/signedness_of_char_test.cc b/src/starboard/nplb/sabi/signedness_of_char_test.cc
index b736e08..97ffe23 100644
--- a/src/starboard/nplb/sabi/signedness_of_char_test.cc
+++ b/src/starboard/nplb/sabi/signedness_of_char_test.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION >= SB_SABI_FILE_VERSION
+#if SB_API_VERSION >= 12
 
 namespace starboard {
 namespace sabi {
@@ -27,4 +27,4 @@
 }  // namespace sabi
 }  // namespace starboard
 
-#endif  // SB_API_VERSION >= SB_SABI_FILE_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/nplb/sabi/size_test.cc b/src/starboard/nplb/sabi/size_test.cc
index 8d55ee9..2876999 100644
--- a/src/starboard/nplb/sabi/size_test.cc
+++ b/src/starboard/nplb/sabi/size_test.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION >= SB_SABI_FILE_VERSION
+#if SB_API_VERSION >= 12
 
 namespace starboard {
 namespace sabi {
@@ -48,4 +48,4 @@
 }  // namespace sabi
 }  // namespace starboard
 
-#endif  // SB_API_VERSION >= SB_SABI_FILE_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/nplb/sabi/struct_alignment_test.cc b/src/starboard/nplb/sabi/struct_alignment_test.cc
index 1bd476a..81ff373 100644
--- a/src/starboard/nplb/sabi/struct_alignment_test.cc
+++ b/src/starboard/nplb/sabi/struct_alignment_test.cc
@@ -17,7 +17,7 @@
 #include "starboard/configuration.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if SB_API_VERSION >= SB_SABI_FILE_VERSION
+#if SB_API_VERSION >= 12
 
 // 8-byte integers make structs 4-byte aligned on x86.
 #if SB_IS(ARCH_X86)
@@ -166,4 +166,4 @@
 
 #undef ALIGNMENT_8_BYTE_INT
 
-#endif  // SB_API_VERSION >= SB_SABI_FILE_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/nplb/speech_recognizer_cancel_test.cc b/src/starboard/nplb/speech_recognizer_cancel_test.cc
index 630e45a..77dbb3c 100644
--- a/src/starboard/nplb/speech_recognizer_cancel_test.cc
+++ b/src/starboard/nplb/speech_recognizer_cancel_test.cc
@@ -20,8 +20,7 @@
 namespace starboard {
 namespace nplb {
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 TEST_F(SpeechRecognizerTest, CancelTestSunnyDay) {
   if (SkipLocale())
@@ -74,7 +73,7 @@
   SbSpeechRecognizerCancel(kSbSpeechRecognizerInvalid);
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 }  // namespace nplb
diff --git a/src/starboard/nplb/speech_recognizer_create_test.cc b/src/starboard/nplb/speech_recognizer_create_test.cc
index 52da0c7..62b1b9a 100644
--- a/src/starboard/nplb/speech_recognizer_create_test.cc
+++ b/src/starboard/nplb/speech_recognizer_create_test.cc
@@ -19,8 +19,7 @@
 namespace starboard {
 namespace nplb {
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 TEST_F(SpeechRecognizerTest, CreateTestSunnyDay) {
   if (SkipLocale())
@@ -30,7 +29,7 @@
   SbSpeechRecognizerDestroy(recognizer);
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 }  // namespace nplb
diff --git a/src/starboard/nplb/speech_recognizer_destroy_test.cc b/src/starboard/nplb/speech_recognizer_destroy_test.cc
index f2f5fe1..9091d83 100644
--- a/src/starboard/nplb/speech_recognizer_destroy_test.cc
+++ b/src/starboard/nplb/speech_recognizer_destroy_test.cc
@@ -19,8 +19,7 @@
 namespace starboard {
 namespace nplb {
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 TEST_F(SpeechRecognizerTest, DestroyInvalidSpeechRecognizer) {
   if (SkipLocale())
@@ -38,7 +37,7 @@
   SbSpeechRecognizerDestroy(recognizer);
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 }  // namespace nplb
diff --git a/src/starboard/nplb/speech_recognizer_helper.h b/src/starboard/nplb/speech_recognizer_helper.h
index 5ab23b0..de4c7d7 100644
--- a/src/starboard/nplb/speech_recognizer_helper.h
+++ b/src/starboard/nplb/speech_recognizer_helper.h
@@ -25,8 +25,7 @@
 namespace starboard {
 namespace nplb {
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 class SpeechRecognizerTest : public ::testing::Test {
  public:
@@ -54,7 +53,7 @@
     // We include all API tests at compile time after Starboard version 12, so
     // we must do a runtime check to determine whether or not that API (and
     // thus the test fixture) is supported.
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
     isTestFixtureSupported = SbSpeechRecognizerIsSupported();
 #else
     isTestFixtureSupported = true;
@@ -83,7 +82,7 @@
   SbSpeechRecognizerHandler handler_;
 };
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 }  // namespace nplb
diff --git a/src/starboard/nplb/speech_recognizer_start_test.cc b/src/starboard/nplb/speech_recognizer_start_test.cc
index 85acebc..3746bae 100644
--- a/src/starboard/nplb/speech_recognizer_start_test.cc
+++ b/src/starboard/nplb/speech_recognizer_start_test.cc
@@ -19,8 +19,7 @@
 namespace starboard {
 namespace nplb {
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 TEST_F(SpeechRecognizerTest, StartTestSunnyDay) {
   if (SkipLocale())
@@ -114,7 +113,7 @@
   EXPECT_FALSE(success);
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 }  // namespace nplb
diff --git a/src/starboard/nplb/speech_recognizer_stop_test.cc b/src/starboard/nplb/speech_recognizer_stop_test.cc
index d8808be..b48526b 100644
--- a/src/starboard/nplb/speech_recognizer_stop_test.cc
+++ b/src/starboard/nplb/speech_recognizer_stop_test.cc
@@ -19,8 +19,7 @@
 namespace starboard {
 namespace nplb {
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 TEST_F(SpeechRecognizerTest, StopIsCalledMultipleTimes) {
   if (SkipLocale())
@@ -40,7 +39,7 @@
   SbSpeechRecognizerDestroy(recognizer);
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 }  // namespace nplb
diff --git a/src/starboard/nplb/speech_synthesis_basic_test.cc b/src/starboard/nplb/speech_synthesis_basic_test.cc
index 65a2f1d..e99e060 100644
--- a/src/starboard/nplb/speech_synthesis_basic_test.cc
+++ b/src/starboard/nplb/speech_synthesis_basic_test.cc
@@ -19,11 +19,10 @@
 namespace nplb {
 namespace {
 
-#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_SYNTHESIS)
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_SYNTHESIS)
 
 TEST(SbSpeechSynthesisBasicTest, Basic) {
-#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
   if (!SbSpeechSynthesisIsSupported()) {
     SB_LOG(INFO) << "Speech synthesis not supported. Test skipped.";
     return;
@@ -33,7 +32,7 @@
   SbSpeechSynthesisCancel();
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_SYNTHESIS)
 
 }  // namespace
diff --git a/src/starboard/nplb/testdata/file_tests/dir_with_files/file11 b/src/starboard/nplb/testdata/file_tests/dir_with_files/file11
new file mode 100644
index 0000000..e1aa36f
--- /dev/null
+++ b/src/starboard/nplb/testdata/file_tests/dir_with_files/file11
@@ -0,0 +1 @@
+file11
diff --git a/src/starboard/nplb/testdata/file_tests/dir_with_files/file12 b/src/starboard/nplb/testdata/file_tests/dir_with_files/file12
new file mode 100644
index 0000000..dd63810
--- /dev/null
+++ b/src/starboard/nplb/testdata/file_tests/dir_with_files/file12
@@ -0,0 +1 @@
+file12
diff --git a/src/starboard/nplb/testdata/file_tests/dir_with_only_subdir/dir_with_files/file21 b/src/starboard/nplb/testdata/file_tests/dir_with_only_subdir/dir_with_files/file21
new file mode 100644
index 0000000..e4c0bb4
--- /dev/null
+++ b/src/starboard/nplb/testdata/file_tests/dir_with_only_subdir/dir_with_files/file21
@@ -0,0 +1 @@
+file21
diff --git a/src/starboard/nplb/testdata/file_tests/dir_with_only_subdir/dir_with_files/file22 b/src/starboard/nplb/testdata/file_tests/dir_with_only_subdir/dir_with_files/file22
new file mode 100644
index 0000000..536442d
--- /dev/null
+++ b/src/starboard/nplb/testdata/file_tests/dir_with_only_subdir/dir_with_files/file22
@@ -0,0 +1 @@
+file22
diff --git a/src/starboard/nplb/testdata/file_tests/file01 b/src/starboard/nplb/testdata/file_tests/file01
new file mode 100644
index 0000000..56b30fe
--- /dev/null
+++ b/src/starboard/nplb/testdata/file_tests/file01
@@ -0,0 +1 @@
+file01
diff --git a/src/starboard/nplb/testdata/file_tests/file_with_long_name_and_contents_for_seek_testing_1234567890 b/src/starboard/nplb/testdata/file_tests/file_with_long_name_and_contents_for_seek_testing_1234567890
new file mode 100644
index 0000000..ac56e62
--- /dev/null
+++ b/src/starboard/nplb/testdata/file_tests/file_with_long_name_and_contents_for_seek_testing_1234567890
@@ -0,0 +1 @@
+file_with_long_name_and_contents_for_seek_testing_1234567890
diff --git a/src/starboard/nplb/thread_local_value_test.cc b/src/starboard/nplb/thread_local_value_test.cc
index 0f02dda..6dfae12 100644
--- a/src/starboard/nplb/thread_local_value_test.cc
+++ b/src/starboard/nplb/thread_local_value_test.cc
@@ -118,9 +118,7 @@
   struct LocalStatic {
     // Used as a fake destructor for thread-local-storage objects in this
     // test.
-    static void CountsDestructorCalls(void* /*value*/) {
-      s_num_destructor_calls++;
-    }
+    static void CountsDestructorCalls(void* value) { s_num_destructor_calls++; }
 
     // Sets a thread local non-NULL value, and then sets it back to NULL.
     static void* ThreadEntryPoint(void* ptr) {
diff --git a/src/starboard/nplb/ui_navigation_test.cc b/src/starboard/nplb/ui_navigation_test.cc
new file mode 100644
index 0000000..329255b
--- /dev/null
+++ b/src/starboard/nplb/ui_navigation_test.cc
@@ -0,0 +1,34 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/ui_navigation.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+#if SB_API_VERSION >= 12
+
+// This verifies that the UI navigation API is not implemented.
+TEST(UiNavigationTest, GetInterface) {
+  SbUiNavInterface interface;
+  EXPECT_FALSE(SbUiNavGetInterface(&interface));
+}
+
+#endif  // SB_API_VERSION >= 12
+
+}  // namespace.
+}  // namespace nplb.
+}  // namespace starboard.
diff --git a/src/starboard/nplb/window_get_platform_handle_test.cc b/src/starboard/nplb/window_get_platform_handle_test.cc
index 1b4d961..04f7de1 100644
--- a/src/starboard/nplb/window_get_platform_handle_test.cc
+++ b/src/starboard/nplb/window_get_platform_handle_test.cc
@@ -27,7 +27,6 @@
   // 0 could actually be a valid value here, because we don't know what the
   // platform uses as its native window handle type, so we can't do any
   // verification here.
-  SB_UNREFERENCED_PARAMETER(handle);
   ASSERT_TRUE(SbWindowDestroy(window));
 }
 
@@ -35,7 +34,6 @@
   void* handle = SbWindowGetPlatformHandle(kSbWindowInvalid);
   // We don't know what the platform's invalid window handle value is, so we
   // can't do any verification here.
-  SB_UNREFERENCED_PARAMETER(handle);
 }
 
 }  // namespace
diff --git a/src/starboard/once.h b/src/starboard/once.h
index 98e8763..beaacb0 100644
--- a/src/starboard/once.h
+++ b/src/starboard/once.h
@@ -28,7 +28,7 @@
 extern "C" {
 #endif
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
 
 // Max size of the SbOnceControl type.
 #define SB_ONCE_MAX_SIZE 64
@@ -53,7 +53,7 @@
   { 0 }
 #endif
 
-#endif  // SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#endif  // SB_API_VERSION >= 12
 
 // Function pointer type for methods that can be called via the SbOnce() system.
 typedef void (*SbOnceInitRoutine)(void);
diff --git a/src/starboard/player.h b/src/starboard/player.h
index c830893..67559e5 100644
--- a/src/starboard/player.h
+++ b/src/starboard/player.h
@@ -39,13 +39,14 @@
   // The decoder is asking for one more sample.
   kSbPlayerDecoderStateNeedsData,
 
+#if SB_API_VERSION < 12
   // The decoder is not ready for any more samples, so do not send them.
   // Note that this enum value has been deprecated and the SbPlayer
   // implementation should no longer use this value.
   kSbPlayerDecoderStateBufferFull,
-
   // The player has been destroyed, and will send no more callbacks.
   kSbPlayerDecoderStateDestroyed,
+#endif  // SB_API_VERSION < 12
 } SbPlayerDecoderState;
 
 // An indicator of the general playback state.
@@ -492,14 +493,14 @@
                                            SbDrmSystem drm_system);
 #endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 
-// Destroys |player|, freeing all associated resources. Each callback must
-// receive one more callback to say that the player was destroyed. Callbacks
-// may be in-flight when SbPlayerDestroy is called, and should be ignored once
-// this function is called.
-//
-// It is not allowed to pass |player| into any other |SbPlayer| function once
-// SbPlayerDestroy has been called on that player.
-//
+// Destroys |player|, freeing all associated resources.
+//  * Upon calling this method, there should be one call to the player status
+//    callback (i.e. |player_status_func| used in the creation of the player)
+//    which indicates the player is destroyed. Note, the callback has to be
+//    in-flight when SbPlayerDestroyed is called.
+//  * No more other callbacks should be issued after this function returns.
+//  * It is not allowed to pass |player| into any other |SbPlayer| function
+//    once SbPlayerDestroy has been called on that player.
 // |player|: The player to be destroyed.
 SB_EXPORT void SbPlayerDestroy(SbPlayer player);
 
@@ -537,45 +538,6 @@
                              SbTime seek_to_timestamp,
                              int ticket);
 
-// Writes a single sample of the given media type to |player|'s input stream.
-// Its data may be passed in via more than one buffers.  The lifetime of
-// |sample_buffers|, |sample_buffer_sizes|, |video_sample_info|, and
-// |sample_drm_info| (as well as member |subsample_mapping| contained inside it)
-// are not guaranteed past the call to SbPlayerWriteSample. That means that
-// before returning, the implementation must synchronously copy any information
-// it wants to retain from those structures.
-//
-// |player|: The player to which the sample is written.
-// |sample_type|: The type of sample being written. See the |SbMediaType|
-//   enum in media.h.
-// |sample_buffers|: A pointer to an array of buffers with
-//   |number_of_sample_buffers| elements that hold the data for this sample. The
-//   buffers are expected to be a portion of a bytestream of the codec type that
-//   the player was created with. The buffers should contain a sequence of whole
-//   NAL Units for video, or a complete audio frame.  |sample_buffers| cannot be
-//   assumed to live past the call into SbPlayerWriteSample(), so it must be
-//   copied if its content will be used after SbPlayerWriteSample() returns.
-// |sample_buffer_sizes|: A pointer to an array of sizes with
-//   |number_of_sample_buffers| elements.  Each of them specify the number of
-//   bytes in the corresponding buffer contained in |sample_buffers|.  None of
-//   them can be 0.  |sample_buffer_sizes| cannot be assumed to live past the
-//   call into SbPlayerWriteSample(), so it must be copied if its content will
-//   be used after SbPlayerWriteSample() returns.
-// |number_of_sample_buffers|: Specify the number of elements contained inside
-//   |sample_buffers| and |sample_buffer_sizes|.  It has to be at least one, or
-//   the call will be ignored.
-// |sample_pts|: The timestamp of the sample in 90KHz ticks (PTS). Note that
-//   samples MAY be written "slightly" out of order.
-// |video_sample_info|: Information about a video sample. This value is
-//   required if |sample_type| is |kSbMediaTypeVideo|. Otherwise, it must be
-//   |NULL|.
-// |sample_drm_info|: The DRM system related info for the media sample. This
-//   value is required for encrypted samples. Otherwise, it must be |NULL|.
-
-// SbPlayerWriteSample2 is like the deprecated SbPlayerWriteSample, but accepts
-// SbTime |sample_timestamp| instead of SbMediaTime |sample_pts|, and also
-// allows writing of multiple samples in one SbPlayerWriteSample2() call.
-
 // Writes samples of the given media type to |player|'s input stream. The
 // lifetime of |sample_infos|, and the members of its elements like |buffer|,
 // |video_sample_info|, and |drm_info| (as well as member |subsample_mapping|
@@ -584,6 +546,8 @@
 // must synchronously copy any information it wants to retain from those
 // structures.
 //
+// SbPlayerWriteSample2 allows writing of multiple samples in one call.
+//
 // |player|: The player to which the sample is written.
 // |sample_type|: The type of sample being written. See the |SbMediaType|
 //   enum in media.h.
diff --git a/src/starboard/raspi/0/cobalt/configuration.py b/src/starboard/raspi/0/cobalt/configuration.py
deleted file mode 100644
index dc9da8d..0000000
--- a/src/starboard/raspi/0/cobalt/configuration.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2016 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Starboard Raspberry Pi 0 Cobalt configuration."""
-
-import cobalt.tools.webdriver_benchmark_config as wb_config
-from starboard.raspi.shared.cobalt import configuration as shared_configuration
-
-
-class CobaltRaspiZeroConfiguration(
-    shared_configuration.CobaltRaspiConfiguration):
-  """Starboard Raspberry Pi 0 Cobalt configuration."""
-
-  def __init__(self, platform_configuration, application_name,
-               application_directory):
-    super(CobaltRaspiZeroConfiguration, self).__init__(
-        platform_configuration, application_name, application_directory)
-
-  def GetDefaultSampleSize(self):
-    return wb_config.REDUCED_SIZE
diff --git a/src/starboard/raspi/0/gyp_configuration.gypi b/src/starboard/raspi/0/gyp_configuration.gypi
deleted file mode 100644
index 51f074f..0000000
--- a/src/starboard/raspi/0/gyp_configuration.gypi
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright 2016 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-{
-  'variables': {
-    # RasPi 1 is ARMv6
-    'arm_version': 6,
-    'armv7': 0,
-    'arm_neon': 0,
-    # Raspi-0 is equipped with hardware Floating-Point-Unit and supports
-    # hardware floating point ABI.
-    'arm_float_abi': 'hard',
-    # Cobalt's default value for arm_fpu is vfpv3 but Raspi-0's FPU is vfpv2.
-    'arm_fpu': 'vfpv2',
-
-    'compiler_flags': [
-      # Optimize for Raspberry Pi 1 chips.
-      '-march=armv6zk',
-      '-mcpu=arm1176jzf-s',
-      '-mfloat-abi=hard',
-      '-mfpu=vfp',
-    ],
-  },
-
-  'target_defaults': {
-    'default_configuration': 'raspi-0_debug',
-    'configurations': {
-      'raspi-0_debug': {
-        'inherit_from': ['debug_base'],
-      },
-      'raspi-0_devel': {
-        'inherit_from': ['devel_base'],
-      },
-      'raspi-0_qa': {
-        'inherit_from': ['qa_base'],
-      },
-      'raspi-0_gold': {
-        'inherit_from': ['gold_base'],
-      },
-    }, # end of configurations
-  },
-
-  'includes': [
-    '../shared/gyp_configuration.gypi',
-  ],
-}
diff --git a/src/starboard/raspi/0/gyp_configuration.py b/src/starboard/raspi/0/gyp_configuration.py
deleted file mode 100644
index 1fdc988..0000000
--- a/src/starboard/raspi/0/gyp_configuration.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright 2016 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Starboard Raspberry Pi 0 platform configuration."""
-
-from starboard.raspi.shared import gyp_configuration as shared_configuration
-from starboard.tools.testing import test_filter
-
-
-class Raspi0PlatformConfig(shared_configuration.RaspiPlatformConfig):
-
-  def __init__(self, platform, sabi_json_path=None):
-    super(Raspi0PlatformConfig, self).__init__(
-        platform, sabi_json_path=sabi_json_path)
-
-  def GetVariables(self, config_name):
-    variables = super(Raspi0PlatformConfig, self).GetVariables(config_name)
-    variables.update({
-        'javascript_engine': 'v8',
-        'cobalt_enable_jit': 1,
-    })
-    return variables
-
-  def GetTestFilters(self):
-    filters = super(Raspi0PlatformConfig, self).GetTestFilters()
-    for target, tests in self.__FILTERED_TESTS.iteritems():
-      filters.extend(test_filter.TestFilter(target, test) for test in tests)
-    return filters
-
-  __FILTERED_TESTS = {
-      'nplb': [
-          # TODO: debug these failures.
-          'SbPlayerTest.MultiPlayer',  # crashes
-      ],
-      'player_filter_tests': [
-          # The implementation for the raspberry pi 0 is incomplete and not
-          # meant to be a reference implementation. As such we will not repair
-          # these failing tests for now.
-          'VideoDecoderTests/VideoDecoderTest.DecodeFullGOP/0',
-          'VideoDecoderTests/VideoDecoderTest.HoldFramesUntilFull/0',
-          'VideoDecoderTests/VideoDecoderTest.MultipleInputs/0',
-          'VideoDecoderTests/VideoDecoderTest.Preroll/0',
-      ]
-  }
-
-
-def CreatePlatformConfig():
-  return Raspi0PlatformConfig(
-      'raspi-0', sabi_json_path='starboard/sabi/arm/hardfp/v6zk/sabi.json')
diff --git a/src/starboard/raspi/2/gyp_configuration.py b/src/starboard/raspi/2/gyp_configuration.py
index dd29994..705bc44 100644
--- a/src/starboard/raspi/2/gyp_configuration.py
+++ b/src/starboard/raspi/2/gyp_configuration.py
@@ -18,7 +18,9 @@
 
 class Raspi2PlatformConfig(shared_configuration.RaspiPlatformConfig):
 
-  def __init__(self, platform, sabi_json_path=None):
+  def __init__(self,
+               platform,
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     super(Raspi2PlatformConfig, self).__init__(
         platform, sabi_json_path=sabi_json_path)
 
@@ -26,11 +28,11 @@
     variables = super(Raspi2PlatformConfig, self).GetVariables(config_name)
     variables.update({
         'javascript_engine': 'v8',
-        'cobalt_enable_jit': 1,
     })
     return variables
 
 
 def CreatePlatformConfig():
   return Raspi2PlatformConfig(
-      'raspi-2', sabi_json_path='starboard/sabi/arm/hardfp/sabi.json')
+      'raspi-2',
+      sabi_json_path='starboard/sabi/arm/hardfp/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/raspi/2/sbversion/12/atomic_public.h
similarity index 67%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/raspi/2/sbversion/12/atomic_public.h
index 0fbc0ef..59ac9b3 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/raspi/2/sbversion/12/atomic_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2017 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_RASPI_2_SBVERSION_12_ATOMIC_PUBLIC_H_
+#define STARBOARD_RASPI_2_SBVERSION_12_ATOMIC_PUBLIC_H_
 
-#include "starboard/raspi/shared/atomic_public.h"
+#include "starboard/raspi/2/atomic_public.h"
 
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#endif  // STARBOARD_RASPI_2_SBVERSION_12_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/raspi/2/sbversion/12/configuration_public.h b/src/starboard/raspi/2/sbversion/12/configuration_public.h
new file mode 100644
index 0000000..da93315
--- /dev/null
+++ b/src/starboard/raspi/2/sbversion/12/configuration_public.h
@@ -0,0 +1,158 @@
+// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The Starboard configuration for Raspberry PI 2 Raspbian.
+
+#ifndef STARBOARD_RASPI_2_SBVERSION_12_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_RASPI_2_SBVERSION_12_CONFIGURATION_PUBLIC_H_
+
+// Configuration parameters that allow the application to make some general
+// compile-time decisions with respect to the the number of cores likely to be
+// available on this platform. For a definitive measure, the application should
+// still call SbSystemGetNumberOfProcessors at runtime.
+
+// --- System Header Configuration -------------------------------------------
+
+// Any system headers listed here that are not provided by the platform will be
+// emulated in starboard/types.h.
+
+// Whether the current platform provides the standard header sys/types.h.
+#define SB_HAS_SYS_TYPES_H 1
+
+// Type detection for wchar_t.
+#if defined(__WCHAR_MAX__) && \
+    (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
+#define SB_IS_WCHAR_T_UTF32 1
+#elif defined(__WCHAR_MAX__) && \
+    (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
+#define SB_IS_WCHAR_T_UTF16 1
+#endif
+
+// Chrome has an exclusion for iOS here, we should too when we support iOS.
+#define SB_IS_WCHAR_T_UNSIGNED 1
+
+// --- Attribute Configuration -----------------------------------------------
+
+// The platform's annotation for forcing a C function to be inlined.
+#define SB_C_FORCE_INLINE __inline__ __attribute__((always_inline))
+
+// The platform's annotation for marking a C function as suggested to be
+// inlined.
+#define SB_C_INLINE inline
+
+// The platform's annotation for marking a C function as forcibly not
+// inlined.
+#define SB_C_NOINLINE __attribute__((noinline))
+
+// The platform's annotation for marking a symbol as exported outside of the
+// current shared library.
+#define SB_EXPORT_PLATFORM __attribute__((visibility("default")))
+
+// The platform's annotation for marking a symbol as imported from outside of
+// the current linking unit.
+#define SB_IMPORT_PLATFORM
+
+// --- Extensions Configuration ----------------------------------------------
+
+// Do not use <unordered_map> and <unordered_set> for the hash table types.
+#define SB_HAS_STD_UNORDERED_HASH 0
+
+// GCC/Clang doesn't define a long long hash function, except for Android and
+// Game consoles.
+#define SB_HAS_LONG_LONG_HASH 0
+
+// GCC/Clang doesn't define a string hash function, except for Game Consoles.
+#define SB_HAS_STRING_HASH 0
+
+// Desktop Linux needs a using statement for the hash functions.
+#define SB_HAS_HASH_USING 0
+
+// Set this to 1 if hash functions for custom types can be defined as a
+// hash_value() function. Otherwise, they need to be placed inside a
+// partially-specified hash struct template with an operator().
+#define SB_HAS_HASH_VALUE 0
+
+// Set this to 1 if use of hash_map or hash_set causes a deprecation warning
+// (which then breaks the build).
+#define SB_HAS_HASH_WARNING 1
+
+// The location to include hash_map on this platform.
+#define SB_HASH_MAP_INCLUDE <ext/hash_map>
+
+// C++'s hash_map and hash_set are often found in different namespaces depending
+// on the compiler.
+#define SB_HASH_NAMESPACE __gnu_cxx
+
+// The location to include hash_set on this platform.
+#define SB_HASH_SET_INCLUDE <ext/hash_set>
+
+// Define this to how this platform copies varargs blocks.
+#define SB_VA_COPY(dest, source) va_copy(dest, source)
+
+// --- Graphics Configuration ------------------------------------------------
+
+// Indicates whether or not the given platform supports bilinear filtering.
+// This can be checked to enable/disable renderer tests that verify that this is
+// working properly.
+#define SB_HAS_BILINEAR_FILTERING_SUPPORT 1
+
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#define SB_HAS_NV12_TEXTURE_SUPPORT 1
+
+// --- I/O Configuration -----------------------------------------------------
+
+// Whether the current platform implements the on screen keyboard interface.
+#define SB_HAS_ON_SCREEN_KEYBOARD 0
+
+// Whether the current platform has speech recognizer.
+#define SB_HAS_SPEECH_RECOGNIZER 0
+
+// Whether the current platform has speech synthesis.
+#define SB_HAS_SPEECH_SYNTHESIS 0
+
+// --- Memory Configuration --------------------------------------------------
+
+// Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is
+// required for platforms that want to JIT.
+#define SB_CAN_MAP_EXECUTABLE_MEMORY 1
+
+// The Raspberry Pi does not apparently align fields in a heap-allocated struct
+// by over 16 bytes.
+#define SB_HAS_QUIRK_DOES_NOT_ALIGN_FIELDS_IN_HEAP_OVER_16_BYTES 1
+
+// The Raspberry Pi does not apparently align stack variables by over 16 bytes.
+#define SB_HAS_QUIRK_DOES_NOT_STACK_ALIGN_OVER_16_BYTES 1
+
+// --- Network Configuration -------------------------------------------------
+
+// Specifies whether this platform supports IPV6.
+#define SB_HAS_IPV6 1
+
+// Specifies whether this platform supports pipe.
+#define SB_HAS_PIPE 1
+
+// --- Timing API ------------------------------------------------------------
+
+// Whether this platform has an API to retrieve how long the current thread
+// has spent in the executing state.
+#define SB_HAS_TIME_THREAD_NOW 1
+
+// --- Platform Specific Audits ----------------------------------------------
+
+#if !defined(__GNUC__)
+#error "RasPi builds need a GCC-like compiler (for the moment)."
+#endif
+
+#endif  // STARBOARD_RASPI_2_SBVERSION_12_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/raspi/2/sbversion/12/gyp_configuration.gypi b/src/starboard/raspi/2/sbversion/12/gyp_configuration.gypi
new file mode 100644
index 0000000..551ac91
--- /dev/null
+++ b/src/starboard/raspi/2/sbversion/12/gyp_configuration.gypi
@@ -0,0 +1,44 @@
+# Copyright 2017 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+  'variables': {
+    'variables': {
+      'sb_evergreen_compatible': 1,
+    },
+  },
+
+  'target_defaults': {
+    'default_configuration': 'raspi-2-sbversion-12_debug',
+    'configurations': {
+      'raspi-2-sbversion-12_debug': {
+        'inherit_from': ['debug_base'],
+      },
+      'raspi-2-sbversion-12_devel': {
+        'inherit_from': ['devel_base'],
+      },
+      'raspi-2-sbversion-12_qa': {
+        'inherit_from': ['qa_base'],
+      },
+      'raspi-2-sbversion-12_gold': {
+        'inherit_from': ['gold_base'],
+      },
+    }, # end of configurations
+  },
+
+  'includes': [
+    '<(DEPTH)/starboard/raspi/2/architecture.gypi',
+    '<(DEPTH)/starboard/raspi/shared/gyp_configuration.gypi',
+  ],
+}
diff --git a/src/starboard/raspi/2/sbversion/12/gyp_configuration.py b/src/starboard/raspi/2/sbversion/12/gyp_configuration.py
new file mode 100644
index 0000000..622f13c
--- /dev/null
+++ b/src/starboard/raspi/2/sbversion/12/gyp_configuration.py
@@ -0,0 +1,26 @@
+# Copyright 2017 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Starboard Raspberry Pi 2 platform configuration."""
+
+import importlib
+
+# Dynamically imported to get around the number in the path.
+_PARENT_CONFIGURATION = importlib.import_module(
+    'starboard.raspi.2.gyp_configuration')
+
+
+def CreatePlatformConfig():
+  return _PARENT_CONFIGURATION.Raspi2PlatformConfig(
+      platform='raspi-2-sbversion-12',
+      sabi_json_path='starboard/sabi/arm/hardfp/sabi-v12.json')
diff --git a/src/starboard/raspi/0/starboard_platform.gyp b/src/starboard/raspi/2/sbversion/12/starboard_platform.gyp
similarity index 75%
copy from src/starboard/raspi/0/starboard_platform.gyp
copy to src/starboard/raspi/2/sbversion/12/starboard_platform.gyp
index 021af7c..b88e4d9 100644
--- a/src/starboard/raspi/0/starboard_platform.gyp
+++ b/src/starboard/raspi/2/sbversion/12/starboard_platform.gyp
@@ -11,8 +11,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 {
   'includes': [
-    '../shared/starboard_platform.gypi',
+    # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file.  The idea
+    # is that we just want this file to *be* the parent gyp file.
+    '<(DEPTH)/starboard/raspi/2/starboard_platform.gyp',
   ],
 }
diff --git a/src/starboard/raspi/0/thread_types_public.h b/src/starboard/raspi/2/sbversion/12/thread_types_public.h
similarity index 65%
rename from src/starboard/raspi/0/thread_types_public.h
rename to src/starboard/raspi/2/sbversion/12/thread_types_public.h
index e131465..39e27a5 100644
--- a/src/starboard/raspi/0/thread_types_public.h
+++ b/src/starboard/raspi/2/sbversion/12/thread_types_public.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2017 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_RASPI_0_THREAD_TYPES_PUBLIC_H_
+#ifndef STARBOARD_RASPI_2_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_RASPI_2_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
 
-#include "starboard/raspi/shared/thread_types_public.h"
+#include "starboard/raspi/2/thread_types_public.h"
 
-#endif  // STARBOARD_RASPI_0_THREAD_TYPES_PUBLIC_H_
+#endif  // STARBOARD_RASPI_2_SBVERSION_12_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/raspi/2/skia/configuration.cc b/src/starboard/raspi/2/skia/configuration.cc
index 0ffdf45..d3af155 100644
--- a/src/starboard/raspi/2/skia/configuration.cc
+++ b/src/starboard/raspi/2/skia/configuration.cc
@@ -23,18 +23,23 @@
 
 namespace {
 
+// This atlas size works better than the auto-mem setting.
 int CobaltSkiaGlyphAtlasWidth() {
   return 2048;
 }
-
 int CobaltSkiaGlyphAtlasHeight() {
   return 2048;
 }
 
 const char* CobaltRasterizerType() {
+  // Use the skia hardware rasterizer.
   return "hardware";
 }
 
+bool CobaltEnableJit() {
+  return true;
+}
+
 const CobaltExtensionConfigurationApi kConfigurationApi = {
     kCobaltExtensionConfigurationName,
     1,
@@ -59,7 +64,7 @@
     &common::CobaltReduceGpuMemoryByDefault,
     &common::CobaltGcZealDefault,
     &CobaltRasterizerType,
-    &common::CobaltEnableJitDefault,
+    &CobaltEnableJit,
 };
 
 }  // namespace
diff --git a/src/starboard/raspi/2/skia/gyp_configuration.gypi b/src/starboard/raspi/2/skia/gyp_configuration.gypi
index bb5762b..62f6615 100644
--- a/src/starboard/raspi/2/skia/gyp_configuration.gypi
+++ b/src/starboard/raspi/2/skia/gyp_configuration.gypi
@@ -13,11 +13,6 @@
 # limitations under the License.
 
 {
-  'variables': {
-    # Use the skia hardware rasterizer.
-    'rasterizer_type': 'hardware',
-  },
-
   'target_defaults': {
     'default_configuration': 'raspi-2-skia_debug',
     'configurations': {
@@ -39,6 +34,5 @@
   'includes': [
     '../architecture.gypi',
     '../../shared/gyp_configuration.gypi',
-    '<(DEPTH)/starboard/sabi/sabi.gypi',
   ],
 }
diff --git a/src/starboard/raspi/2/skia/gyp_configuration.py b/src/starboard/raspi/2/skia/gyp_configuration.py
index 4cb713a..ba8654c 100644
--- a/src/starboard/raspi/2/skia/gyp_configuration.py
+++ b/src/starboard/raspi/2/skia/gyp_configuration.py
@@ -22,4 +22,5 @@
 
 def CreatePlatformConfig():
   return Raspi2PlatformConfig(
-      'raspi-2-skia', sabi_json_path='starboard/sabi/arm/hardfp/sabi.json')
+      'raspi-2-skia',
+      sabi_json_path='starboard/sabi/arm/hardfp/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/raspi/shared/cobalt/configuration.gypi b/src/starboard/raspi/shared/cobalt/configuration.gypi
index f922cf2..bec52cf 100644
--- a/src/starboard/raspi/shared/cobalt/configuration.gypi
+++ b/src/starboard/raspi/shared/cobalt/configuration.gypi
@@ -17,9 +17,5 @@
 {
   'variables': {
     'in_app_dial%': 0,
-
-    # This atlas size works better than the auto-mem setting.
-    'skia_glyph_atlas_width%': '2048',
-    'skia_glyph_atlas_height%': '2048',
   }, # end of variables
 }
diff --git a/src/starboard/raspi/shared/configuration.cc b/src/starboard/raspi/shared/configuration.cc
index 5dc4c10..a0587e8 100644
--- a/src/starboard/raspi/shared/configuration.cc
+++ b/src/starboard/raspi/shared/configuration.cc
@@ -23,10 +23,10 @@
 
 namespace {
 
+// This atlas size works better than the auto-mem setting.
 int CobaltSkiaGlyphAtlasWidth() {
   return 2048;
 }
-
 int CobaltSkiaGlyphAtlasHeight() {
   return 2048;
 }
diff --git a/src/starboard/raspi/shared/configuration_constants.cc b/src/starboard/raspi/shared/configuration_constants.cc
index b81883f..6816391 100644
--- a/src/starboard/raspi/shared/configuration_constants.cc
+++ b/src/starboard/raspi/shared/configuration_constants.cc
@@ -52,9 +52,6 @@
 // Allow ac3 and ec3 support
 const bool kSbHasAc3Audio = true;
 
-// Specifies whether this platform updates audio frames asynchronously.
-const bool kSbHasAsyncAudioFramesReporting = false;
-
 // Specifies whether this platform has webm/vp9 support.  This should be set to
 // non-zero on platforms with webm/vp9 support.
 const bool kSbHasMediaWebmVp9Support = false;
diff --git a/src/starboard/raspi/shared/configuration_public.h b/src/starboard/raspi/shared/configuration_public.h
index 8623dcd..7237fde 100644
--- a/src/starboard/raspi/shared/configuration_public.h
+++ b/src/starboard/raspi/shared/configuration_public.h
@@ -169,7 +169,7 @@
 
 // Whether this platform has and should use an MMAP function to map physical
 // memory to the virtual address space.
-#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#if SB_API_VERSION < 12
 #define SB_HAS_MMAP 1
 #endif
 
diff --git a/src/starboard/raspi/shared/gyp_configuration.py b/src/starboard/raspi/shared/gyp_configuration.py
index 5abd0c8..65e4796 100644
--- a/src/starboard/raspi/shared/gyp_configuration.py
+++ b/src/starboard/raspi/shared/gyp_configuration.py
@@ -35,7 +35,9 @@
 class RaspiPlatformConfig(platform_configuration.PlatformConfiguration):
   """Starboard Raspberry Pi platform configuration."""
 
-  def __init__(self, platform, sabi_json_path=None):
+  def __init__(self,
+               platform,
+               sabi_json_path='starboard/sabi/default/sabi.json'):
     super(RaspiPlatformConfig, self).__init__(platform)
     self.AppendApplicationConfigurationPath(os.path.dirname(__file__))
     self.raspi_home = os.environ.get('RASPI_HOME', _UNDEFINED_RASPI_HOME)
@@ -65,8 +67,11 @@
     return variables
 
   def GetEnvironmentVariables(self):
-    env_variables = build.GetHostCompilerEnvironment(
-        clang_specification.GetClangSpecification(), False)
+    if not hasattr(self, 'host_compiler_environment'):
+      self.host_compiler_environment = build.GetHostCompilerEnvironment(
+          clang_specification.GetClangSpecification(), False)
+
+    env_variables = self.host_compiler_environment
     toolchain = os.path.realpath(
         os.path.join(
             self.raspi_home,
@@ -88,7 +93,7 @@
       raise RuntimeError('RasPi builds require $RASPI_HOME/sysroot '
                          'to be a valid directory.')
 
-  def GetTargetToolchain(self):
+  def GetTargetToolchain(self, **kwargs):
     environment_variables = self.GetEnvironmentVariables()
     cc_path = environment_variables['CC']
     cxx_path = environment_variables['CXX']
@@ -106,7 +111,7 @@
         bash.Shell(),
     ]
 
-  def GetHostToolchain(self):
+  def GetHostToolchain(self, **kwargs):
     environment_variables = self.GetEnvironmentVariables()
     cc_path = environment_variables['CC_host']
     cxx_path = environment_variables['CXX_host']
diff --git a/src/starboard/raspi/shared/media_is_video_supported.cc b/src/starboard/raspi/shared/media_is_video_supported.cc
index 04ef357..704faea 100644
--- a/src/starboard/raspi/shared/media_is_video_supported.cc
+++ b/src/starboard/raspi/shared/media_is_video_supported.cc
@@ -32,10 +32,6 @@
                              int64_t bitrate,
                              int fps,
                              bool decode_to_texture_required) {
-  SB_UNREFERENCED_PARAMETER(content_type);
-  SB_UNREFERENCED_PARAMETER(profile);
-  SB_UNREFERENCED_PARAMETER(level);
-
   using starboard::shared::starboard::media::IsSDRVideo;
 
   if (!IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id)) {
diff --git a/src/starboard/raspi/shared/open_max/open_max_component.cc b/src/starboard/raspi/shared/open_max/open_max_component.cc
index 182e704..94c03da 100644
--- a/src/starboard/raspi/shared/open_max/open_max_component.cc
+++ b/src/starboard/raspi/shared/open_max/open_max_component.cc
@@ -215,8 +215,9 @@
   SendCommandAndWaitForCompletion(OMX_CommandStateSet, OMX_StateLoaded);
 }
 
-void OpenMaxComponent::OnErrorEvent(OMX_U32 data1, OMX_U32 data2,
-                                    OMX_PTR /* event_data */) {
+void OpenMaxComponent::OnErrorEvent(OMX_U32 data1,
+                                    OMX_U32 data2,
+                                    OMX_PTR event_data) {
   SB_NOTREACHED() << "OMX_EventError received with " << std::hex << data1
                   << " " << data2;
 }
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.cc b/src/starboard/raspi/shared/open_max/video_decoder.cc
index 712ff8b..d9ad900 100644
--- a/src/starboard/raspi/shared/open_max/video_decoder.cc
+++ b/src/starboard/raspi/shared/open_max/video_decoder.cc
@@ -73,7 +73,9 @@
     const scoped_refptr<InputBuffer>& input_buffer) {
   SB_DCHECK(input_buffer);
   SB_DCHECK(decoder_status_cb_);
+  SB_DCHECK(!eos_written_);
 
+  first_input_written_ = true;
   queue_.Put(new Event(input_buffer));
   if (!TryToDeliverOneFrame()) {
     SbThreadSleep(kSbTimeMillisecond);
@@ -84,12 +86,21 @@
 }
 
 void VideoDecoder::WriteEndOfStream() {
-  queue_.Put(new Event(Event::kWriteEOS));
   eos_written_ = true;
+  if (first_input_written_) {
+    queue_.Put(new Event(Event::kWriteEOS));
+  } else {
+    decoder_status_cb_(kNeedMoreInput, VideoFrame::CreateEOSFrame());
+  }
 }
 
 void VideoDecoder::Reset() {
   queue_.Put(new Event(Event::kReset));
+  // TODO: we should introduce a wait here for |queue_| to be fully processed
+  // before returning however the wait time is very long (over 40 seconds).
+  // The cause for the long wait is unknown and should be investigated.
+  eos_written_ = false;
+  first_input_written_ = false;
 }
 
 void VideoDecoder::Update() {
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.h b/src/starboard/raspi/shared/open_max/video_decoder.h
index e4e6492..7dc899e 100644
--- a/src/starboard/raspi/shared/open_max/video_decoder.h
+++ b/src/starboard/raspi/shared/open_max/video_decoder.h
@@ -84,6 +84,7 @@
   DecoderStatusCB decoder_status_cb_;
   ErrorCB error_cb_;
   bool eos_written_;
+  bool first_input_written_ = false;
 
   SbThread thread_;
   bool request_thread_termination_;
diff --git a/src/starboard/raspi/shared/starboard_platform.gypi b/src/starboard/raspi/shared/starboard_platform.gypi
index 63f2be3..f1215a6 100644
--- a/src/starboard/raspi/shared/starboard_platform.gypi
+++ b/src/starboard/raspi/shared/starboard_platform.gypi
@@ -265,6 +265,8 @@
         '<(DEPTH)/starboard/shared/signal/crash_signals.h',
         '<(DEPTH)/starboard/shared/signal/suspend_signals.cc',
         '<(DEPTH)/starboard/shared/signal/suspend_signals.h',
+        '<(DEPTH)/starboard/shared/signal/system_request_conceal.cc',
+        '<(DEPTH)/starboard/shared/signal/system_request_freeze.cc',
         '<(DEPTH)/starboard/shared/signal/system_request_suspend.cc',
         '<(DEPTH)/starboard/shared/starboard/application.cc',
         '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
@@ -317,6 +319,7 @@
         '<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc',
         '<(DEPTH)/starboard/shared/starboard/media/mime_type.cc',
         '<(DEPTH)/starboard/shared/starboard/media/mime_type.h',
+        '<(DEPTH)/starboard/shared/starboard/memory.cc',
         '<(DEPTH)/starboard/shared/starboard/new.cc',
         '<(DEPTH)/starboard/shared/starboard/player/decoded_audio_internal.cc',
         '<(DEPTH)/starboard/shared/starboard/player/decoded_audio_internal.h',
@@ -349,7 +352,10 @@
         '<(DEPTH)/starboard/shared/starboard/string_copy_wide.cc',
         '<(DEPTH)/starboard/shared/starboard/string_duplicate.cc',
         '<(DEPTH)/starboard/shared/starboard/system_get_random_uint64.cc',
+        '<(DEPTH)/starboard/shared/starboard/system_request_blur.cc',
+        '<(DEPTH)/starboard/shared/starboard/system_request_focus.cc',
         '<(DEPTH)/starboard/shared/starboard/system_request_pause.cc',
+        '<(DEPTH)/starboard/shared/starboard/system_request_reveal.cc',
         '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc',
         '<(DEPTH)/starboard/shared/starboard/system_request_unpause.cc',
         '<(DEPTH)/starboard/shared/starboard/system_supports_resume.cc',
@@ -368,6 +374,7 @@
         '<(DEPTH)/starboard/shared/stub/drm_create_system.cc',
         '<(DEPTH)/starboard/shared/stub/drm_destroy_system.cc',
         '<(DEPTH)/starboard/shared/stub/drm_generate_session_update_request.cc',
+        '<(DEPTH)/starboard/shared/stub/drm_get_metrics.cc',
         '<(DEPTH)/starboard/shared/stub/drm_is_server_certificate_updatable.cc',
         '<(DEPTH)/starboard/shared/stub/drm_system_internal.h',
         '<(DEPTH)/starboard/shared/stub/drm_update_server_certificate.cc',
diff --git a/src/starboard/raspi/shared/system_get_property.cc b/src/starboard/raspi/shared/system_get_property.cc
index deb8c38..ceae991 100644
--- a/src/starboard/raspi/shared/system_get_property.cc
+++ b/src/starboard/raspi/shared/system_get_property.cc
@@ -16,6 +16,8 @@
 
 #include <sys/utsname.h>
 
+#include <cstring>
+#include <memory>
 #include <string>
 
 #if SB_API_VERSION >= 11
@@ -26,8 +28,92 @@
 
 namespace {
 
+const char* kBrandName = "Raspberry Pi Foundation";
+
+const char* kModelRevision = "Rev";
+
 const char* kFriendlyName = "Raspberry Pi";
 
+// Read device model from /proc/device-tree/model
+const char* GetModelName() {
+  const char* file_path = "/proc/device-tree/model";
+  // Size of the raw data
+  size_t file_data_size;
+
+  file_data_size = 0;
+  // Get the size of the file by reading it until the end. This is
+  // required because files under /proc do not always return a valid size
+  // when using fseek(0, SEEK_END) + ftell(). Nor can the be mmap()-ed.
+  FILE* file = fopen(file_path, "r");
+  if (file != nullptr) {
+    for (;;) {
+      char file_buffer[256];
+      size_t data_size = fread(file_buffer, 1, sizeof(file_buffer), file);
+      if (data_size == 0) {
+        break;
+      }
+      file_data_size += data_size;
+    }
+    fclose(file);
+  }
+
+  const size_t kFileSizeCap = 1000;
+  if (file_data_size > kFileSizeCap) {
+    SB_LOG(ERROR)
+        << "File too large: /proc/device-tree/model is larger than 1KB.";
+    return "";
+  }
+
+  // Read the contents of the /proc/device-tree/model file.
+  const size_t kFileDataSize = file_data_size + 1;
+  char file_data[kFileDataSize];
+  char* file_data_ptr = file_data;
+  memset(file_data_ptr, 0, file_data_size + 1);
+
+  file = fopen(file_path, "r");
+  if (file != nullptr) {
+    for (size_t offset = 0; offset < file_data_size;) {
+      size_t data_size =
+          fread(file_data_ptr + offset, 1, file_data_size - offset, file);
+      if (data_size == 0) {
+        break;
+      }
+      offset += data_size;
+    }
+    fclose(file);
+  }
+
+  // Zero-terminate the first line of the file because the model name is in the
+  // first line
+  for (int i = 0; i < file_data_size; i++) {
+    if (file_data_ptr[i] == '\n') {
+      file_data_ptr[i] = '\0';
+      break;
+    }
+  }
+
+  // Zero-terminate the file data
+  file_data_ptr[file_data_size] = '\0';
+
+  // Get Model name
+  std::string model_string(const_cast<char*>(file_data));
+  std::string model_name;
+
+  // Find the revision number of the model name and remove it if present
+  int model_rev_pos = model_string.find(kModelRevision);
+  if (model_rev_pos != std::string::npos) {
+    model_name = model_string.substr(0, model_rev_pos);
+  }
+
+  // Trim trailing spaces
+  size_t end = model_name.find_last_not_of(" \t");
+  if (end != std::string::npos) {
+    return model_name.substr(0, end + 1).c_str();
+  } else {
+    return "";
+  }
+}
+
 bool CopyStringAndTestIfSuccess(char* out_value,
                                 int value_length,
                                 const char* from_value) {
@@ -48,9 +134,14 @@
 
   switch (property_id) {
     case kSbSystemPropertyBrandName:
+      return CopyStringAndTestIfSuccess(out_value, value_length, kBrandName);
+
+    case kSbSystemPropertyModelName:
+      return CopyStringAndTestIfSuccess(out_value, value_length,
+                                        GetModelName());
+
     case kSbSystemPropertyChipsetModelNumber:
     case kSbSystemPropertyFirmwareVersion:
-    case kSbSystemPropertyModelName:
     case kSbSystemPropertyModelYear:
 #if SB_API_VERSION >= 11
     case kSbSystemPropertyOriginalDesignManufacturerName:
diff --git a/src/starboard/raspi/shared/thread_create_priority.cc b/src/starboard/raspi/shared/thread_create_priority.cc
index 8aa3b2d..6fcdb96 100644
--- a/src/starboard/raspi/shared/thread_create_priority.cc
+++ b/src/starboard/raspi/shared/thread_create_priority.cc
@@ -23,8 +23,7 @@
 namespace shared {
 namespace pthread {
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(THREAD_PRIORITY_SUPPORT)
+#if SB_API_VERSION >= 12 || SB_HAS(THREAD_PRIORITY_SUPPORT)
 // This is the maximum priority that will be passed to SetRoundRobinScheduler().
 const int kMaxRoundRobinPriority = 2;
 
@@ -131,7 +130,7 @@
   }
 }
 
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(THREAD_PRIORITY_SUPPORT)
 
 }  // namespace pthread
diff --git a/src/starboard/sabi/arm/hardfp/sabi.json b/src/starboard/sabi/arm/hardfp/sabi-v12.json
similarity index 100%
rename from src/starboard/sabi/arm/hardfp/sabi.json
rename to src/starboard/sabi/arm/hardfp/sabi-v12.json
diff --git a/src/starboard/sabi/arm/hardfp/sabi-v13.json b/src/starboard/sabi/arm/hardfp/sabi-v13.json
new file mode 100644
index 0000000..c0a7a8a
--- /dev/null
+++ b/src/starboard/sabi/arm/hardfp/sabi-v13.json
@@ -0,0 +1,32 @@
+{
+  "variables": {
+    "sb_api_version": 13,
+    "target_arch": "arm",
+    "target_arch_sub": "v7a",
+    "word_size": 32,
+    "endianness": "little",
+    "calling_convention": "eabi",
+    "floating_point_abi": "hard",
+    "floating_point_fpu": "vfpv3",
+    "signedness_of_char": "signed",
+    "signedness_of_enum": "signed",
+    "alignment_char":    1,
+    "alignment_double":  8,
+    "alignment_float":   4,
+    "alignment_int":     4,
+    "alignment_llong":   8,
+    "alignment_long":    4,
+    "alignment_pointer": 4,
+    "alignment_short":   2,
+    "size_of_char":    1,
+    "size_of_double":  8,
+    "size_of_enum":    4,
+    "size_of_float":   4,
+    "size_of_int":     4,
+    "size_of_llong":   8,
+    "size_of_long":    4,
+    "size_of_pointer": 4,
+    "size_of_short":   2
+  }
+}
+
diff --git a/src/starboard/sabi/arm/hardfp/v6zk/sabi.json b/src/starboard/sabi/arm/hardfp/v6zk/sabi-v12.json
similarity index 100%
rename from src/starboard/sabi/arm/hardfp/v6zk/sabi.json
rename to src/starboard/sabi/arm/hardfp/v6zk/sabi-v12.json
diff --git a/src/starboard/sabi/arm/hardfp/v6zk/sabi-v13.json b/src/starboard/sabi/arm/hardfp/v6zk/sabi-v13.json
new file mode 100644
index 0000000..b78046d
--- /dev/null
+++ b/src/starboard/sabi/arm/hardfp/v6zk/sabi-v13.json
@@ -0,0 +1,32 @@
+{
+  "variables": {
+    "sb_api_version": 13,
+    "target_arch": "arm",
+    "target_arch_sub": "v6zk",
+    "word_size": 32,
+    "endianness": "little",
+    "calling_convention": "eabi",
+    "floating_point_abi": "hard",
+    "floating_point_fpu": "vfpv2",
+    "signedness_of_char": "signed",
+    "signedness_of_enum": "signed",
+    "alignment_char":    1,
+    "alignment_double":  8,
+    "alignment_float":   4,
+    "alignment_int":     4,
+    "alignment_llong":   8,
+    "alignment_long":    4,
+    "alignment_pointer": 4,
+    "alignment_short":   2,
+    "size_of_char":    1,
+    "size_of_double":  8,
+    "size_of_enum":    4,
+    "size_of_float":   4,
+    "size_of_int":     4,
+    "size_of_llong":   8,
+    "size_of_long":    4,
+    "size_of_pointer": 4,
+    "size_of_short":   2
+  }
+}
+
diff --git a/src/starboard/sabi/arm/softfp/sabi.json b/src/starboard/sabi/arm/softfp/sabi-v12.json
similarity index 100%
rename from src/starboard/sabi/arm/softfp/sabi.json
rename to src/starboard/sabi/arm/softfp/sabi-v12.json
diff --git a/src/starboard/sabi/arm/softfp/sabi-v13.json b/src/starboard/sabi/arm/softfp/sabi-v13.json
new file mode 100644
index 0000000..aa4735d
--- /dev/null
+++ b/src/starboard/sabi/arm/softfp/sabi-v13.json
@@ -0,0 +1,32 @@
+{
+  "variables": {
+    "sb_api_version": 13,
+    "target_arch": "arm",
+    "target_arch_sub": "v7a",
+    "word_size": 32,
+    "endianness": "little",
+    "calling_convention": "eabi",
+    "floating_point_abi": "softfp",
+    "floating_point_fpu": "vfpv3",
+    "signedness_of_char": "signed",
+    "signedness_of_enum": "signed",
+    "alignment_char":    1,
+    "alignment_double":  8,
+    "alignment_float":   4,
+    "alignment_int":     4,
+    "alignment_llong":   8,
+    "alignment_long":    4,
+    "alignment_pointer": 4,
+    "alignment_short":   2,
+    "size_of_char":    1,
+    "size_of_double":  8,
+    "size_of_enum":    4,
+    "size_of_float":   4,
+    "size_of_int":     4,
+    "size_of_llong":   8,
+    "size_of_long":    4,
+    "size_of_pointer": 4,
+    "size_of_short":   2
+  }
+}
+
diff --git a/src/starboard/sabi/arm64/sabi.json b/src/starboard/sabi/arm64/sabi-v12.json
similarity index 100%
rename from src/starboard/sabi/arm64/sabi.json
rename to src/starboard/sabi/arm64/sabi-v12.json
diff --git a/src/starboard/sabi/arm64/sabi-v13.json b/src/starboard/sabi/arm64/sabi-v13.json
new file mode 100644
index 0000000..bcc7a70
--- /dev/null
+++ b/src/starboard/sabi/arm64/sabi-v13.json
@@ -0,0 +1,32 @@
+{
+  "variables": {
+    "sb_api_version": 13,
+    "target_arch": "arm64",
+    "target_arch_sub": "v8a",
+    "word_size": 64,
+    "endianness": "little",
+    "calling_convention": "aarch64",
+    "floating_point_abi": "",
+    "floating_point_fpu": "",
+    "signedness_of_char": "signed",
+    "signedness_of_enum": "signed",
+    "alignment_char":    1,
+    "alignment_double":  8,
+    "alignment_float":   4,
+    "alignment_int":     4,
+    "alignment_llong":   8,
+    "alignment_long":    8,
+    "alignment_pointer": 8,
+    "alignment_short":   2,
+    "size_of_char":    1,
+    "size_of_double":  8,
+    "size_of_enum":    4,
+    "size_of_float":   4,
+    "size_of_int":     4,
+    "size_of_llong":   8,
+    "size_of_long":    8,
+    "size_of_pointer": 8,
+    "size_of_short":   2
+  }
+}
+
diff --git a/src/starboard/raspi/0/starboard_platform.gyp b/src/starboard/sabi/sabi.py
similarity index 77%
rename from src/starboard/raspi/0/starboard_platform.gyp
rename to src/starboard/sabi/sabi.py
index 021af7c..09d04a3 100644
--- a/src/starboard/raspi/0/starboard_platform.gyp
+++ b/src/starboard/sabi/sabi.py
@@ -1,4 +1,4 @@
-# Copyright 2017 The Cobalt Authors. All Rights Reserved.
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -11,8 +11,6 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-{
-  'includes': [
-    '../shared/starboard_platform.gypi',
-  ],
-}
+"""Source of truth of the default/experimental Starboard API version."""
+
+SB_API_VERSION = 13
diff --git a/src/starboard/sabi/sabi_utils.py b/src/starboard/sabi/sabi_utils.py
index ec75285..4a279af 100644
--- a/src/starboard/sabi/sabi_utils.py
+++ b/src/starboard/sabi/sabi_utils.py
@@ -19,10 +19,38 @@
 
 import json
 import os
+import re
 
+from starboard.sabi import sabi
 from starboard.tools import build
 from starboard.tools import paths
 
+SABI_SCHEMA_PATH = os.path.join(paths.STARBOARD_ROOT, 'sabi', 'schema')
+SB_API_VERSION_FROM_SABI_RE = re.compile('sabi-v([0-9]+).json')
+
+
+def _PlatformToSabiFile(platform):
+  """Returns the Starboard ABI file for the given platform.
+
+  Args:
+    platform: The platform of the desired Starboard ABI file.
+
+  Raises:
+    ValueError: When |platform| is not provided, or when |platform| is provided
+      and it fails to load the platform configuration.
+
+  Returns:
+    The path to the Starboard ABI file associated with the provided platform.
+  """
+  if not platform:
+    raise ValueError('A platform must be specified.')
+  platform_configuration = build.GetPlatformConfig(platform)
+  if not platform_configuration:
+    raise ValueError('Failed to get platform configuration.')
+  filename = platform_configuration.GetPathToSabiJsonFile().format(
+      sb_api_version=sabi.SB_API_VERSION)
+  return os.path.join(paths.REPOSITORY_ROOT, filename)
+
 
 def AddSabiArguments(arg_parser):
   group = arg_parser.add_mutually_exclusive_group(required=True)
@@ -41,7 +69,7 @@
 
 
 def LoadSabi(filename=None, platform=None):
-  """Return the absolute path to a Starboard ABI file and its contents.
+  """Returns the contents of the desired Starboard ABI file.
 
   This function will use either the provided |filename| or the provided
   |platform| to locate the desired Starboard ABI file.
@@ -52,8 +80,7 @@
     platform: The platform of the desired Starboard ABI file.
 
   Raises:
-    ValueError: When both |filename| and |platform| are provided, or when
-      |platform| is provided and it fails to load the platform configuration.
+    ValueError: When both |filename| and |platform| are provided.
 
   Returns:
     The contents of the desired Starboard ABI file.
@@ -61,10 +88,40 @@
   if (filename and platform) or (not filename and not platform):
     raise ValueError('Either |filename| or |platform| must be provided.')
   if platform:
-    platform_configuration = build.GetPlatformConfig(platform)
-    if not platform_configuration:
-      raise ValueError('Failed to get platform configuration.')
-    filename = platform_configuration.GetPathToSabiJsonFile()
-    filename = os.path.join(paths.REPOSITORY_ROOT, filename)
+    filename = _PlatformToSabiFile(platform)
   with open(filename) as f:
     return json.load(f)['variables']
+
+
+def LoadSabiSchema(filename=None, platform=None):
+  """Returns the contents of the schema associated with the Starboard ABI file.
+
+  Args:
+    filename: The path, can be relative or absolute, to the desired Starboard
+      ABI schema file.
+    platform: A platform whose Starboard ABI file can be validated with the
+      desired Starboard ABI schema file.
+
+  Raises:
+    ValueError: When both |filename| and |platform| are provided, or when
+      |platform| is provided and Starboard API version could not be parsed
+      from the associated Starboard ABI filename.
+
+  Returns:
+    The contents of the schema associated with the provided Starboard ABI file.
+  """
+  if (filename and platform) or (not filename and not platform):
+    raise ValueError('Either |filename| or |platform| must be provided.')
+  if platform:
+    filename = _PlatformToSabiFile(platform)
+    filename = os.path.basename(filename)
+    match = SB_API_VERSION_FROM_SABI_RE.search(filename)
+    if not match:
+      raise ValueError(
+          'The Starboard API version could not be parsed from the filename: {}'
+          .format(filename))
+    filename = os.path.join(
+        SABI_SCHEMA_PATH, 'sabi-v{sb_api_version}.schema.json'.format(
+            sb_api_version=match.group(1)))
+  with open(filename) as f:
+    return json.load(f)
diff --git a/src/starboard/sabi/sabi.schema.json b/src/starboard/sabi/schema/sabi-v12.schema.json
similarity index 100%
copy from src/starboard/sabi/sabi.schema.json
copy to src/starboard/sabi/schema/sabi-v12.schema.json
diff --git a/src/starboard/sabi/schema/sabi-v13.schema.json b/src/starboard/sabi/schema/sabi-v13.schema.json
new file mode 100644
index 0000000..6196f17
--- /dev/null
+++ b/src/starboard/sabi/schema/sabi-v13.schema.json
@@ -0,0 +1,172 @@
+{
+  "title": "Starboard ABI Schema",
+  "description": "This schema validates that a Starboard ABI file contains the required keys, no extras, and that the corresponding values are valid.",
+  "type": "object",
+  "properties": {
+    "sb_api_version": {
+      "type": "integer",
+      "description": "The Starboard API version.",
+      "enum": [13]
+    },
+    "target_arch": {
+      "type": "string",
+      "description": "The targeted architecture.",
+      "enum": ["arm", "arm64", "x86", "x64"]
+    },
+    "target_arch_sub": {
+      "type": "string",
+      "description": "The targeted sub-architecture.",
+      "enum": ["v6zk", "v7a", "v8a", ""]
+    },
+    "word_size": {
+      "type": "integer",
+      "description": "The word size.",
+      "enum": [32, 64]
+    },
+    "endianness": {
+      "type": "string",
+      "description": "The endianness.",
+      "enum": ["big", "little"]
+    },
+    "calling_convention": {
+      "type": "string",
+      "description": "The calling convention.",
+      "enum": ["sysv", "eabi", "windows", "aarch64"]
+    },
+    "floating_point_abi": {
+      "type": "string",
+      "description": "The floating-point ABI.",
+      "enum": ["hard", "softfp", ""]
+    },
+    "floating_point_fpu": {
+      "type": "string",
+      "description": "The floating-point hardware, if available.",
+      "enum": ["vfpv2", "vfpv3", ""]
+    },
+    "signedness_of_char": {
+      "type": "string",
+      "description": "The signedness of the 'char' data type.",
+      "enum": ["signed", "unsigned"]
+    },
+    "signedness_of_enum": {
+      "type": "string",
+      "description": "The signedness of the 'enum' data type.",
+      "enum": ["signed", "unsigned"]
+    },
+    "alignment_char": {
+      "type": "integer",
+      "description": "The alignment of the 'char' data type.",
+      "enum": [1]
+    },
+    "alignment_double": {
+      "type": "integer",
+      "description": "The alignment of the 'double' data type.",
+      "enum": [8]
+    },
+    "alignment_float": {
+      "type": "integer",
+      "description": "The alignment of the 'float' data type.",
+      "enum": [4]
+    },
+    "alignment_int": {
+      "type": "integer",
+      "description": "The alignment of the 'int' data type.",
+      "enum": [4]
+    },
+    "alignment_llong": {
+      "type": "integer",
+      "description": "The alignment of the 'long long' data type.",
+      "enum": [8]
+    },
+    "alignment_long": {
+      "type": "integer",
+      "description": "The alignment of the 'long' data type.",
+      "enum": [4, 8]
+    },
+    "alignment_pointer": {
+      "type": "integer",
+      "description": "The alignment of pointers.",
+      "enum": [4, 8]
+    },
+    "alignment_short": {
+      "type": "integer",
+      "description": "The alignment of the 'short' data type.",
+      "enum": [2]
+    },
+    "size_of_char": {
+      "type": "integer",
+      "description": "The size of the 'char' data type.",
+      "enum": [1]
+    },
+    "size_of_double": {
+      "type": "integer",
+      "description": "The size of the 'double' data type.",
+      "enum": [8]
+    },
+    "size_of_enum": {
+      "type": "integer",
+      "description": "The size of the 'enum' data type.",
+      "enum": [4]
+    },
+    "size_of_float": {
+      "type": "integer",
+      "description": "The size of the 'float' data type.",
+      "enum": [4]
+    },
+    "size_of_int": {
+      "type": "integer",
+      "description": "The size of the 'int' data type.",
+      "enum": [4]
+    },
+    "size_of_llong": {
+      "type": "integer",
+      "description": "The size of the 'long long' data type.",
+      "enum": [8]
+    },
+    "size_of_long": {
+      "type": "integer",
+      "description": "The size of the 'long' data type.",
+      "enum": [4, 8]
+    },
+    "size_of_pointer": {
+      "type": "integer",
+      "description": "The size of pointers.",
+      "enum": [4, 8]
+    },
+    "size_of_short": {
+      "type": "integer",
+      "description": "The size of the 'short' data type.",
+      "enum": [2]
+    }
+  },
+  "required": [
+    "sb_api_version",
+    "target_arch",
+    "target_arch_sub",
+    "word_size",
+    "endianness",
+    "calling_convention",
+    "floating_point_abi",
+    "floating_point_fpu",
+    "signedness_of_char",
+    "signedness_of_enum",
+    "alignment_char",
+    "alignment_double",
+    "alignment_float",
+    "alignment_int",
+    "alignment_llong",
+    "alignment_long",
+    "alignment_pointer",
+    "alignment_short",
+    "size_of_char",
+    "size_of_enum",
+    "size_of_double",
+    "size_of_float",
+    "size_of_int",
+    "size_of_llong",
+    "size_of_long",
+    "size_of_pointer",
+    "size_of_short"
+  ],
+  "additionalProperties": false
+}
diff --git a/src/starboard/sabi/sabi.schema.json b/src/starboard/sabi/test/sabi.schema.json
similarity index 100%
rename from src/starboard/sabi/sabi.schema.json
rename to src/starboard/sabi/test/sabi.schema.json
diff --git a/src/starboard/sabi/validate_sabi.py b/src/starboard/sabi/validate_sabi.py
index 78b0eb5..88e3e61 100644
--- a/src/starboard/sabi/validate_sabi.py
+++ b/src/starboard/sabi/validate_sabi.py
@@ -18,12 +18,9 @@
 import _env  # pylint: disable=unused-import
 
 import argparse
-import json
-import os
 import sys
 
 from starboard.sabi import sabi_utils
-from starboard.tools import paths
 
 # Starboard ABI files are considered invalid unless 'jsonschema' is installed
 # and used to verify them.
@@ -32,25 +29,21 @@
 except ImportError:
   jsonschema = None
 
-_STARBOARD_ABI_JSON_SCHEMA_PATH = os.path.join(paths.STARBOARD_ROOT, 'sabi',
-                                               'sabi.schema.json')
 
-
-def ValidateSabi(sabi_json):
+def ValidateSabi(sabi_json, schema_json):
   """Validates the provided Starboard ABI JSON with a jsonschema schema.
 
   Args:
     sabi_json: The Starboard ABI JSON to be validated.
+    schema_json: The Starboard ABI schema JSON to validate with.
 
   Returns:
     |True| if the provided Starboard ABI JSON is valid. |False| if jsonschema
     could not be imported, or if the Starboard ABI JSON is invalid.
   """
-  with open(_STARBOARD_ABI_JSON_SCHEMA_PATH) as f:
-    schema = json.load(f)
   try:
     if jsonschema:
-      jsonschema.validate(sabi_json, schema=schema)
+      jsonschema.validate(sabi_json, schema=schema_json)
       return True
     print("Please install 'jsonschema' to use this tool.")
   except (jsonschema.SchemaError, jsonschema.ValidationError) as e:
@@ -62,7 +55,9 @@
   arg_parser = argparse.ArgumentParser()
   sabi_utils.AddSabiArguments(arg_parser)
   args, _ = arg_parser.parse_known_args()
-  return ValidateSabi(sabi_utils.LoadSabi(args.filename, args.platform))
+  return ValidateSabi(
+      sabi_utils.LoadSabi(args.filename, args.platform),
+      sabi_utils.LoadSabiSchema(args.filename, args.platform))
 
 
 if __name__ == '__main__':
diff --git a/src/starboard/sabi/validate_sabi_test.py b/src/starboard/sabi/validate_sabi_test.py
index 500a683..4610184 100644
--- a/src/starboard/sabi/validate_sabi_test.py
+++ b/src/starboard/sabi/validate_sabi_test.py
@@ -26,38 +26,47 @@
 from starboard.sabi import validate_sabi
 from starboard.tools import paths
 
-_TEST_SABI_PATH = os.path.join(paths.STARBOARD_ROOT, 'sabi', 'test',
-                               'sabi.json')
-_TEST_SABI_JSON = sabi_utils.LoadSabi(_TEST_SABI_PATH, None)
+_TEST_SABI_JSON = sabi_utils.LoadSabi(
+    os.path.join(paths.STARBOARD_ROOT, 'sabi', 'test', 'sabi.json'), None)
+_TEST_SABI_SCHEMA = sabi_utils.LoadSabiSchema(
+    os.path.join(paths.STARBOARD_ROOT, 'sabi', 'test', 'sabi.schema.json'),
+    None)
 
 
 class ValidateSabiTest(unittest.TestCase):
 
   def testSunnyDayValidateSabi(self):
-    self.assertTrue(validate_sabi.ValidateSabi(_TEST_SABI_JSON))
+    self.assertTrue(
+        validate_sabi.ValidateSabi(_TEST_SABI_JSON, _TEST_SABI_SCHEMA))
 
   def testSunnyDayValidateSabiAllSabiFiles(self):
     for root, _, files in os.walk(os.path.join(paths.STARBOARD_ROOT, 'sabi')):
       if os.path.basename(root) == 'default':
         continue
-      if 'sabi.json' in files:
-        sabi_json = sabi_utils.LoadSabi(os.path.join(root, 'sabi.json'), None)
-        self.assertTrue(validate_sabi.ValidateSabi(sabi_json))
+      for f in files:
+        match = sabi_utils.SB_API_VERSION_FROM_SABI_RE.search(f)
+        if match:
+          sabi_schema_path = os.path.join(
+              sabi_utils.SABI_SCHEMA_PATH,
+              'sabi-v{}.schema.json'.format(match.group(1)))
+          sabi_json = sabi_utils.LoadSabi(os.path.join(root, f), None)
+          sabi_schema = sabi_utils.LoadSabiSchema(sabi_schema_path, None)
+          self.assertTrue(validate_sabi.ValidateSabi(sabi_json, sabi_schema))
 
   def testRainyDayValidateSabiSabiJsonWithMissingEntry(self):
     sabi_json = copy.deepcopy(_TEST_SABI_JSON)
     _, _ = sabi_json.popitem()
-    self.assertFalse(validate_sabi.ValidateSabi(sabi_json))
+    self.assertFalse(validate_sabi.ValidateSabi(sabi_json, _TEST_SABI_SCHEMA))
 
   def testRainyDayValidateSabiSabiJsonWithExtraEntry(self):
     sabi_json = copy.deepcopy(_TEST_SABI_JSON)
     sabi_json['invalid_key'] = 'invalid_value'
-    self.assertFalse(validate_sabi.ValidateSabi(sabi_json))
+    self.assertFalse(validate_sabi.ValidateSabi(sabi_json, _TEST_SABI_SCHEMA))
 
   def testRainyDayValidateSabiSabiJsonWithInvalidEntry(self):
     sabi_json = copy.deepcopy(_TEST_SABI_JSON)
     sabi_json[sabi_json.keys()[0]] = 'invalid_value'
-    self.assertFalse(validate_sabi.ValidateSabi(sabi_json))
+    self.assertFalse(validate_sabi.ValidateSabi(sabi_json, _TEST_SABI_SCHEMA))
 
 
 if __name__ == '__main__':
diff --git a/src/starboard/sabi/x64/sysv/sabi.json b/src/starboard/sabi/x64/sysv/sabi-v12.json
similarity index 100%
rename from src/starboard/sabi/x64/sysv/sabi.json
rename to src/starboard/sabi/x64/sysv/sabi-v12.json
diff --git a/src/starboard/sabi/x64/sysv/sabi-v13.json b/src/starboard/sabi/x64/sysv/sabi-v13.json
new file mode 100644
index 0000000..171f997
--- /dev/null
+++ b/src/starboard/sabi/x64/sysv/sabi-v13.json
@@ -0,0 +1,32 @@
+{
+  "variables": {
+    "sb_api_version": 13,
+    "target_arch": "x64",
+    "target_arch_sub": "",
+    "word_size": 64,
+    "endianness": "little",
+    "calling_convention": "sysv",
+    "floating_point_abi": "",
+    "floating_point_fpu": "",
+    "signedness_of_char": "signed",
+    "signedness_of_enum": "signed",
+    "alignment_char":    1,
+    "alignment_double":  8,
+    "alignment_float":   4,
+    "alignment_int":     4,
+    "alignment_llong":   8,
+    "alignment_long":    8,
+    "alignment_pointer": 8,
+    "alignment_short":   2,
+    "size_of_char":    1,
+    "size_of_double":  8,
+    "size_of_enum":    4,
+    "size_of_float":   4,
+    "size_of_int":     4,
+    "size_of_llong":   8,
+    "size_of_long":    8,
+    "size_of_pointer": 8,
+    "size_of_short":   2
+  }
+}
+
diff --git a/src/starboard/sabi/x64/windows/sabi.json b/src/starboard/sabi/x64/windows/sabi-v12.json
similarity index 100%
rename from src/starboard/sabi/x64/windows/sabi.json
rename to src/starboard/sabi/x64/windows/sabi-v12.json
diff --git a/src/starboard/sabi/x64/windows/sabi-v13.json b/src/starboard/sabi/x64/windows/sabi-v13.json
new file mode 100644
index 0000000..f6b0f98
--- /dev/null
+++ b/src/starboard/sabi/x64/windows/sabi-v13.json
@@ -0,0 +1,32 @@
+{
+  "variables": {
+    "sb_api_version": 13,
+    "target_arch": "x64",
+    "target_arch_sub": "",
+    "word_size": 64,
+    "endianness": "little",
+    "calling_convention": "windows",
+    "floating_point_abi": "",
+    "floating_point_fpu": "",
+    "signedness_of_char": "signed",
+    "signedness_of_enum": "signed",
+    "alignment_char":    1,
+    "alignment_double":  8,
+    "alignment_float":   4,
+    "alignment_int":     4,
+    "alignment_llong":   8,
+    "alignment_long":    4,
+    "alignment_pointer": 8,
+    "alignment_short":   2,
+    "size_of_char":    1,
+    "size_of_double":  8,
+    "size_of_enum":    4,
+    "size_of_float":   4,
+    "size_of_int":     4,
+    "size_of_llong":   8,
+    "size_of_long":    4,
+    "size_of_pointer": 8,
+    "size_of_short":   2
+  }
+}
+
diff --git a/src/starboard/sabi/x86/sabi.json b/src/starboard/sabi/x86/sabi-v12.json
similarity index 100%
rename from src/starboard/sabi/x86/sabi.json
rename to src/starboard/sabi/x86/sabi-v12.json
diff --git a/src/starboard/sabi/x86/sabi-v13.json b/src/starboard/sabi/x86/sabi-v13.json
new file mode 100644
index 0000000..d50a396
--- /dev/null
+++ b/src/starboard/sabi/x86/sabi-v13.json
@@ -0,0 +1,32 @@
+{
+  "variables": {
+    "sb_api_version": 13,
+    "target_arch": "x86",
+    "target_arch_sub": "",
+    "word_size": 32,
+    "endianness": "little",
+    "calling_convention": "sysv",
+    "floating_point_abi": "",
+    "floating_point_fpu": "",
+    "signedness_of_char": "signed",
+    "signedness_of_enum": "signed",
+    "alignment_char":    1,
+    "alignment_double":  8,
+    "alignment_float":   4,
+    "alignment_int":     4,
+    "alignment_llong":   8,
+    "alignment_long":    4,
+    "alignment_pointer": 4,
+    "alignment_short":   2,
+    "size_of_char":    1,
+    "size_of_double":  8,
+    "size_of_enum":    4,
+    "size_of_float":   4,
+    "size_of_int":     4,
+    "size_of_llong":   8,
+    "size_of_long":    4,
+    "size_of_pointer": 4,
+    "size_of_short":   2
+  }
+}
+
diff --git a/src/starboard/shared/alsa/alsa_audio_sink_type.cc b/src/starboard/shared/alsa/alsa_audio_sink_type.cc
index 6d54dc8..bea8991 100644
--- a/src/starboard/shared/alsa/alsa_audio_sink_type.cc
+++ b/src/starboard/shared/alsa/alsa_audio_sink_type.cc
@@ -88,7 +88,7 @@
                 SbAudioSinkFrameBuffers frame_buffers,
                 int frames_per_channel,
                 SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-                SbAudioSinkConsumeFramesFunc consume_frame_func,
+                ConsumeFramesFunc consume_frames_func,
                 void* context);
   ~AlsaAudioSink() override;
 
@@ -128,7 +128,7 @@
 
   Type* type_;
   SbAudioSinkUpdateSourceStatusFunc update_source_status_func_;
-  SbAudioSinkConsumeFramesFunc consume_frame_func_;
+  ConsumeFramesFunc consume_frames_func_;
   void* context_;
 
   double playback_rate_;
@@ -162,7 +162,7 @@
     SbAudioSinkFrameBuffers frame_buffers,
     int frames_per_channel,
     SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-    SbAudioSinkConsumeFramesFunc consume_frame_func,
+    ConsumeFramesFunc consume_frames_func,
     void* context)
     : type_(type),
       playback_rate_(1.0),
@@ -173,7 +173,7 @@
       sampling_frequency_hz_(sampling_frequency_hz),
       sample_type_(sample_type),
       update_source_status_func_(update_source_status_func),
-      consume_frame_func_(consume_frame_func),
+      consume_frames_func_(consume_frames_func),
       context_(context),
       audio_out_thread_(kSbThreadInvalid),
       creation_signal_(mutex_),
@@ -186,7 +186,7 @@
                                   GetSampleSize(sample_type)]),
       playback_handle_(NULL) {
   SB_DCHECK(update_source_status_func_);
-  SB_DCHECK(consume_frame_func_);
+  SB_DCHECK(consume_frames_func_);
   SB_DCHECK(frame_buffer_);
   SB_DCHECK(SbAudioSinkIsAudioSampleTypeSupported(sample_type_));
 
@@ -346,12 +346,7 @@
           IncrementPointerByBytes(frame_buffer_,
                                   offset_in_frames * bytes_per_frame),
           frames_to_buffer_end);
-      consume_frame_func_(
-          consumed,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-          (SbTime)kSbTimeMax,  // Async audio frames reporting not supported
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-          context_);
+      consume_frames_func_(consumed, SbTimeGetMonotonicNow(), context_);
       if (consumed != frames_to_buffer_end) {
         SB_DLOG(INFO) << "alsa::AlsaAudioSink exits write frames : consumed "
                       << consumed << " frames, with " << frames_to_buffer_end
@@ -368,12 +363,7 @@
                         IncrementPointerByBytes(
                             frame_buffer_, offset_in_frames * bytes_per_frame),
                         frames_to_write);
-    consume_frame_func_(
-        consumed,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-        (SbTime)kSbTimeMax,  // Async audio frames reporting not supported
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-        context_);
+    consume_frames_func_(consumed, SbTimeGetMonotonicNow(), context_);
   } else {
     // A very low quality resampler that simply shift the audio frames to play
     // at the right time.
@@ -402,12 +392,8 @@
 
     int consumed =
         AlsaWriteFrames(playback_handle_, &resample_buffer_[0], target_frames);
-    consume_frame_func_(
-        consumed * playback_rate_,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-        (SbTime)kSbTimeMax,  // Async audio frames reporting not supported
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-        context_);
+    consume_frames_func_(consumed * playback_rate_, SbTimeGetMonotonicNow(),
+                         context_);
   }
 }
 
@@ -421,11 +407,11 @@
       SbAudioSinkFrameBuffers frame_buffers,
       int frames_per_channel,
       SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-      SbAudioSinkConsumeFramesFunc consume_frames_func,
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+      SbAudioSinkPrivate::ConsumeFramesFunc consume_frames_func,
+#if SB_API_VERSION >= 12
       SbAudioSinkPrivate::ErrorFunc error_func,
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
-      void* context);
+#endif  // SB_API_VERSION >= 12
+      void* context) override;
 
   bool IsValid(SbAudioSink audio_sink) override {
     return audio_sink != kSbAudioSinkInvalid && audio_sink->IsType(this);
@@ -448,10 +434,10 @@
     SbAudioSinkFrameBuffers frame_buffers,
     int frames_per_channel,
     SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-    SbAudioSinkConsumeFramesFunc consume_frames_func,
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+    SbAudioSinkPrivate::ConsumeFramesFunc consume_frames_func,
+#if SB_API_VERSION >= 12
     SbAudioSinkPrivate::ErrorFunc error_func,
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#endif  // SB_API_VERSION >= 12
     void* context) {
   AlsaAudioSink* audio_sink = new AlsaAudioSink(
       this, channels, sampling_frequency_hz, audio_sample_type, frame_buffers,
diff --git a/src/starboard/shared/blittergles/blitter_is_blitter_supported.cc b/src/starboard/shared/blittergles/blitter_is_blitter_supported.cc
index 0a6e9e9..8980f2e 100644
--- a/src/starboard/shared/blittergles/blitter_is_blitter_supported.cc
+++ b/src/starboard/shared/blittergles/blitter_is_blitter_supported.cc
@@ -14,10 +14,10 @@
 
 #include "starboard/blitter.h"
 
-#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbBlitterIsBlitterSupported() {
   return true;
 }
 
-#endif  // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/shared/directfb/blitter_is_blitter_supported.cc b/src/starboard/shared/directfb/blitter_is_blitter_supported.cc
index 0a6e9e9..8980f2e 100644
--- a/src/starboard/shared/directfb/blitter_is_blitter_supported.cc
+++ b/src/starboard/shared/directfb/blitter_is_blitter_supported.cc
@@ -14,10 +14,10 @@
 
 #include "starboard/blitter.h"
 
-#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbBlitterIsBlitterSupported() {
   return true;
 }
 
-#endif  // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/shared/dlmalloc/page_internal.h b/src/starboard/shared/dlmalloc/page_internal.h
index 6b1d5ca..b4df31f 100644
--- a/src/starboard/shared/dlmalloc/page_internal.h
+++ b/src/starboard/shared/dlmalloc/page_internal.h
@@ -73,8 +73,7 @@
 //
 // See also dlmalloc_config.h which controls some dlmalloc behavior.
 
-#if SB_API_VERSION < SB_VIRTUAL_REGIONS_FLAG_DEPRECATED && \
-    SB_HAS(VIRTUAL_REGIONS)
+#if SB_API_VERSION < 12 && SB_HAS(VIRTUAL_REGIONS)
 // Reserves a virtual address space |size_bytes| big, without mapping any
 // physical pages to that range, returning a pointer to the beginning of the
 // reserved virtual address range. To get memory that is actually usable and
@@ -101,10 +100,10 @@
 
 // How big of a virtual region dlmalloc should allocate.
 size_t SbPageGetVirtualRegionSize();
-#endif  // SB_API_VERSION < SB_VIRTUAL_REGIONS_FLAG_DEPRECATED &&
+#endif  // SB_API_VERSION < 12 &&
         // SB_HAS(VIRTUAL_REGIONS)
 
-#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#if SB_API_VERSION >= 12 || SB_HAS(MMAP)
 // Allocates |size_bytes| worth of physical memory pages and maps them into an
 // available virtual region. On some platforms, |name| appears in the debugger
 // and can be up to 32 bytes. Returns SB_MEMORY_MAP_FAILED on failure, as NULL
@@ -132,7 +131,7 @@
 // Change the protection of |size_bytes| of physical pages, starting from
 // |virtual_address|, to |flags|, returning |true| on success.
 bool SbPageProtect(void* virtual_address, int64_t size_bytes, int flags);
-#endif  // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(MMAP)
 
 // Returns the total amount, in bytes, of physical memory available. Should
 // always be a multiple of kSbMemoryPageSize.
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc
index ae422cb..3d8f090 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc
@@ -43,12 +43,12 @@
   switch (audio_codec) {
     case kSbMediaAudioCodecAac:
       return AV_CODEC_ID_AAC;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || SB_HAS(AC3_AUDIO)
+#if SB_API_VERSION >= 12 || SB_HAS(AC3_AUDIO)
     case kSbMediaAudioCodecAc3:
       return kSbHasAc3Audio ? AV_CODEC_ID_AC3 : AV_CODEC_ID_NONE;
     case kSbMediaAudioCodecEac3:
       return kSbHasAc3Audio ? AV_CODEC_ID_EAC3 : AV_CODEC_ID_NONE;
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(AC3_AUDIO)
     case kSbMediaAudioCodecOpus:
       return AV_CODEC_ID_OPUS;
diff --git a/src/starboard/shared/iso/directory_get_next.cc b/src/starboard/shared/iso/directory_get_next.cc
index 101ef08..3422b26 100644
--- a/src/starboard/shared/iso/directory_get_next.cc
+++ b/src/starboard/shared/iso/directory_get_next.cc
@@ -16,16 +16,16 @@
 
 #include "starboard/shared/iso/impl/directory_get_next.h"
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
 bool SbDirectoryGetNext(SbDirectory directory,
                         char* out_entry,
                         size_t out_entry_size) {
   return ::starboard::shared::iso::impl::SbDirectoryGetNext(
       directory, out_entry, out_entry_size);
 }
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else   // SB_API_VERSION >= 12
 bool SbDirectoryGetNext(SbDirectory directory, SbDirectoryEntry* out_entry) {
   return ::starboard::shared::iso::impl::SbDirectoryGetNext(directory,
                                                             out_entry);
 }
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/shared/iso/impl/directory_get_next.h b/src/starboard/shared/iso/impl/directory_get_next.h
index 712ca0e..5954b93 100644
--- a/src/starboard/shared/iso/impl/directory_get_next.h
+++ b/src/starboard/shared/iso/impl/directory_get_next.h
@@ -33,43 +33,32 @@
 namespace impl {
 
 bool SbDirectoryGetNext(SbDirectory directory,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
                         char* out_entry,
                         size_t out_entry_size) {
   if (out_entry_size < kSbFileMaxName) {
     return false;
   }
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else  // SB_API_VERSION >= 12
                         SbDirectoryEntry* out_entry) {
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
   if (!directory || !directory->directory || !out_entry) {
     return false;
   }
 
-  // Look for the first directory that isn't current or parent.
   struct dirent dirent_buffer;
   struct dirent* dirent;
-  int result;
-  do {
-    result = readdir_r(directory->directory, &dirent_buffer, &dirent);
-    if (!result && dirent) {
-      if ((SbStringCompareAll(dirent->d_name, ".") == 0) ||
-          (SbStringCompareAll(dirent->d_name, "..") == 0)) {
-        continue;
-      } else {
-        break;
-      }
-    } else {
-      return false;
-    }
-  } while (true);
+  int result = readdir_r(directory->directory, &dirent_buffer, &dirent);
+  if (result || !dirent) {
+    return false;
+  }
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
   SbStringCopy(out_entry, dirent->d_name, out_entry_size);
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else   // SB_API_VERSION >= 12
   SbStringCopy(out_entry->name, dirent->d_name,
                SB_ARRAY_SIZE_INT(out_entry->name));
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
 
   return true;
 }
diff --git a/src/starboard/shared/libevent/socket_waiter_internal.cc b/src/starboard/shared/libevent/socket_waiter_internal.cc
index 86b5500..7ab3a4b 100644
--- a/src/starboard/shared/libevent/socket_waiter_internal.cc
+++ b/src/starboard/shared/libevent/socket_waiter_internal.cc
@@ -304,7 +304,7 @@
 }
 
 // static
-void SbSocketWaiterPrivate::LibeventSocketCallback(int /*fd*/,
+void SbSocketWaiterPrivate::LibeventSocketCallback(int fd,
                                                    int16_t event,
                                                    void* context) {
   Waitee* waitee = reinterpret_cast<Waitee*>(context);
@@ -312,15 +312,15 @@
 }
 
 // static
-void SbSocketWaiterPrivate::LibeventTimeoutCallback(int /*fd*/,
-                                                    int16_t /*event*/,
+void SbSocketWaiterPrivate::LibeventTimeoutCallback(int fd,
+                                                    int16_t event,
                                                     void* context) {
   reinterpret_cast<SbSocketWaiter>(context)->WakeUp(true);
 }
 
 // static
-void SbSocketWaiterPrivate::LibeventWakeUpCallback(int /*fd*/,
-                                                   int16_t /*event*/,
+void SbSocketWaiterPrivate::LibeventWakeUpCallback(int fd,
+                                                   int16_t event,
                                                    void* context) {
   reinterpret_cast<SbSocketWaiter>(context)->HandleWakeUpRead();
 }
diff --git a/src/starboard/shared/libevent/socket_waiter_internal.h b/src/starboard/shared/libevent/socket_waiter_internal.h
index 312aa64..55127af 100644
--- a/src/starboard/shared/libevent/socket_waiter_internal.h
+++ b/src/starboard/shared/libevent/socket_waiter_internal.h
@@ -87,19 +87,15 @@
 
   // The libevent callback function, which in turn calls the registered callback
   // function for the Waitee.
-  static void LibeventSocketCallback(int /*fd*/, int16_t events, void* context);
+  static void LibeventSocketCallback(int fd, int16_t events, void* context);
 
   // A libevent callback function that wakes up the SbSocketWaiter given in
   // |context| due to a timeout.
-  static void LibeventTimeoutCallback(int /*fd*/,
-                                      int16_t /*event*/,
-                                      void* context);
+  static void LibeventTimeoutCallback(int fd, int16_t event, void* context);
 
   // A libevent callback function that wakes up the SbSocketWaiter given in
   // |context| due to an external call to WakeUp.
-  static void LibeventWakeUpCallback(int /*fd*/,
-                                     int16_t /*event*/,
-                                     void* context);
+  static void LibeventWakeUpCallback(int fd, int16_t event, void* context);
 
   // Handles a libevent callback.
   void HandleSignal(Waitee* waitee, short events);  // NOLINT[runtime/int]
diff --git a/src/starboard/shared/libjpeg/jpeg_image_decoder.cc b/src/starboard/shared/libjpeg/jpeg_image_decoder.cc
index c0be8f8..cbd6adb 100644
--- a/src/starboard/shared/libjpeg/jpeg_image_decoder.cc
+++ b/src/starboard/shared/libjpeg/jpeg_image_decoder.cc
@@ -46,12 +46,10 @@
 }
 
 void SourceManagerInitSource(j_decompress_ptr decompress_ptr) {
-  SB_UNREFERENCED_PARAMETER(decompress_ptr);
   // no-op.
 }
 
 boolean SourceManagerFillInputBuffer(j_decompress_ptr decompress_ptr) {
-  SB_UNREFERENCED_PARAMETER(decompress_ptr);
   // Normally, this function is called when we need to read more of the encoded
   // buffer into memory and a return false indicates that we have no data to
   // supply yet, but in our case, the encoded buffer is always in memory, so
@@ -62,13 +60,10 @@
 
 boolean SourceManagerResyncToRestart(j_decompress_ptr decompress_ptr,
                                      int desired) {
-  SB_UNREFERENCED_PARAMETER(decompress_ptr);
-  SB_UNREFERENCED_PARAMETER(desired);
   return false;
 }
 
 void SourceManagerTermSource(j_decompress_ptr decompress_ptr) {
-  SB_UNREFERENCED_PARAMETER(decompress_ptr);
   // no-op.
 }
 
diff --git a/src/starboard/shared/linux/cpu_features_get.cc b/src/starboard/shared/linux/cpu_features_get.cc
index 8dface2..8659a64 100644
--- a/src/starboard/shared/linux/cpu_features_get.cc
+++ b/src/starboard/shared/linux/cpu_features_get.cc
@@ -656,9 +656,9 @@
     features->x86.has_tsc = (cpuid_info[3] & (1 << 4)) != 0;
 
     features->x86.has_sse3 = (cpuid_info[2] & (1 << 0)) != 0;
-#if defined(SB_CPU_FEATURE_PCLMULQDQ)
+#if SB_API_VERSION >= 12
     features->x86.has_pclmulqdq = (cpuid_info[2] & (1 << 1)) != 0;
-#endif  // defined(SB_CPU_FEATURE_PCLMULQDQ)
+#endif  // SB_API_VERSION >= 12
     features->x86.has_ssse3 = (cpuid_info[2] & (1 << 9)) != 0;
     features->x86.has_sse41 = (cpuid_info[2] & (1 << 19)) != 0;
     features->x86.has_sse42 = (cpuid_info[2] & (1 << 20)) != 0;
diff --git a/src/starboard/shared/linux/dev_input/dev_input.cc b/src/starboard/shared/linux/dev_input/dev_input.cc
index a834764..4eb284a 100644
--- a/src/starboard/shared/linux/dev_input/dev_input.cc
+++ b/src/starboard/shared/linux/dev_input/dev_input.cc
@@ -769,7 +769,7 @@
   }
 
   while (true) {
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
     std::vector<char> entry(kSbFileMaxName);
 
     if (!SbDirectoryGetNext(directory, entry.data(), kSbFileMaxName)) {
@@ -779,7 +779,7 @@
     std::string path = kDevicePath;
     path += "/";
     path += entry.data();
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else   // SB_API_VERSION >= 12
     SbDirectoryEntry entry;
 
     if (!SbDirectoryGetNext(directory, &entry)) {
@@ -789,7 +789,7 @@
     std::string path = kDevicePath;
     path += "/";
     path += entry.name;
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
 
     if (SbDirectoryCanOpen(path.c_str())) {
       // This is a subdirectory. Skip.
diff --git a/src/starboard/shared/linux/page_internal.cc b/src/starboard/shared/linux/page_internal.cc
index b9cdbaf..bd8c444 100644
--- a/src/starboard/shared/linux/page_internal.cc
+++ b/src/starboard/shared/linux/page_internal.cc
@@ -62,7 +62,7 @@
 
 }  // namespace
 
-void* SbPageMap(size_t size_bytes, int flags, const char* /*unused_name*/) {
+void* SbPageMap(size_t size_bytes, int flags, const char* unused_name) {
   void* ret = SbPageMapUntracked(size_bytes, flags, NULL);
   if (ret != SB_MEMORY_MAP_FAILED) {
     SbAtomicNoBarrier_Increment(&s_tracked_page_count,
@@ -73,7 +73,7 @@
 
 void* SbPageMapUntracked(size_t size_bytes,
                          int flags,
-                         const char* /*unused_name*/) {
+                         const char* unused_name) {
 #if SB_CAN(MAP_EXECUTABLE_MEMORY)
   if (flags & kSbMemoryMapProtectExec) {
     // Cobalt does not allow mapping executable memory directly.
diff --git a/src/starboard/shared/media_session/stub_playback_state.cc b/src/starboard/shared/media_session/stub_playback_state.cc
index e540b48..ae469ef 100644
--- a/src/starboard/shared/media_session/stub_playback_state.cc
+++ b/src/starboard/shared/media_session/stub_playback_state.cc
@@ -21,7 +21,6 @@
 namespace media_session {
 
 void UpdateActiveSessionPlatformPlaybackState(PlaybackState state) {
-  SB_UNREFERENCED_PARAMETER(state);
   SB_NOTIMPLEMENTED();
 }
 
diff --git a/src/starboard/shared/posix/file_atomic_replace.cc b/src/starboard/shared/posix/file_atomic_replace.cc
index 7d86485..b59e785 100644
--- a/src/starboard/shared/posix/file_atomic_replace.cc
+++ b/src/starboard/shared/posix/file_atomic_replace.cc
@@ -22,7 +22,7 @@
 #include "starboard/configuration_constants.h"
 #include "starboard/shared/starboard/file_atomic_replace_write_file.h"
 
-#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#if SB_API_VERSION >= 12
 
 namespace {
 
@@ -56,4 +56,4 @@
   return true;
 }
 
-#endif  // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/shared/posix/log.cc b/src/starboard/shared/posix/log.cc
index a4b02e4..5be55ca 100644
--- a/src/starboard/shared/posix/log.cc
+++ b/src/starboard/shared/posix/log.cc
@@ -23,7 +23,6 @@
 #endif  // SB_API_VERSION >= 11
 
 void SbLog(SbLogPriority priority, const char* message) {
-  SB_UNREFERENCED_PARAMETER(priority);
 #if SB_API_VERSION < 11
   fprintf(stderr, "%s", message);
   fflush(stderr);
diff --git a/src/starboard/shared/posix/socket_is_ipv6_supported.cc b/src/starboard/shared/posix/socket_is_ipv6_supported.cc
index 2d60d16..8ae972b 100644
--- a/src/starboard/shared/posix/socket_is_ipv6_supported.cc
+++ b/src/starboard/shared/posix/socket_is_ipv6_supported.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/socket.h"
 
-#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbSocketIsIpv6Supported() {
   return SB_HAS_IPV6;
diff --git a/src/starboard/shared/posix/time_is_time_thread_now_supported.cc b/src/starboard/shared/posix/time_is_time_thread_now_supported.cc
index dda22a9..a97d2cc 100644
--- a/src/starboard/shared/posix/time_is_time_thread_now_supported.cc
+++ b/src/starboard/shared/posix/time_is_time_thread_now_supported.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/time.h"
 
-#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbTimeIsTimeThreadNowSupported() {
   return true;
diff --git a/src/starboard/shared/pthread/condition_variable_create.cc b/src/starboard/shared/pthread/condition_variable_create.cc
index c8dab74..f5731ea 100644
--- a/src/starboard/shared/pthread/condition_variable_create.cc
+++ b/src/starboard/shared/pthread/condition_variable_create.cc
@@ -45,7 +45,7 @@
 }  // namespace
 
 bool SbConditionVariableCreate(SbConditionVariable* out_condition,
-                               SbMutex* /*opt_mutex*/) {
+                               SbMutex* opt_mutex) {
   SB_COMPILE_ASSERT(
       sizeof(SbConditionVariable) >= sizeof(SbConditionVariablePrivate),
       sb_condition_variable_private_larger_than_sb_condition_variable);
diff --git a/src/starboard/shared/pthread/mutex_acquire.cc b/src/starboard/shared/pthread/mutex_acquire.cc
index 796d99f..67f26b4 100644
--- a/src/starboard/shared/pthread/mutex_acquire.cc
+++ b/src/starboard/shared/pthread/mutex_acquire.cc
@@ -29,7 +29,7 @@
     return kSbMutexDestroyed;
   }
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
   if (!EnsureInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state))) {
     *SB_PTHREAD_INTERNAL_MUTEX(mutex) = PTHREAD_MUTEX_INITIALIZER;
     SetInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state));
diff --git a/src/starboard/shared/pthread/mutex_acquire_try.cc b/src/starboard/shared/pthread/mutex_acquire_try.cc
index 5ec2db7..4c216a5 100644
--- a/src/starboard/shared/pthread/mutex_acquire_try.cc
+++ b/src/starboard/shared/pthread/mutex_acquire_try.cc
@@ -28,7 +28,7 @@
     return kSbMutexDestroyed;
   }
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
   if (!EnsureInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state))) {
     *SB_PTHREAD_INTERNAL_MUTEX(mutex) = PTHREAD_MUTEX_INITIALIZER;
     SetInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state));
diff --git a/src/starboard/shared/pthread/mutex_create.cc b/src/starboard/shared/pthread/mutex_create.cc
index fb6f65a..e72884d 100644
--- a/src/starboard/shared/pthread/mutex_create.cc
+++ b/src/starboard/shared/pthread/mutex_create.cc
@@ -24,7 +24,7 @@
 using starboard::shared::starboard::SetInitialized;
 
 bool SbMutexCreate(SbMutex* mutex) {
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
   SB_COMPILE_ASSERT(sizeof(SbMutex) >= sizeof(SbMutexPrivate),
                     sb_mutex_private_larger_than_sb_mutex);
 #endif
@@ -32,7 +32,7 @@
     return false;
   }
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
   SetInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state));
 #endif
   return IsSuccess(pthread_mutex_init(SB_PTHREAD_INTERNAL_MUTEX(mutex), NULL));
diff --git a/src/starboard/shared/pthread/mutex_destroy.cc b/src/starboard/shared/pthread/mutex_destroy.cc
index df01a41..c131595 100644
--- a/src/starboard/shared/pthread/mutex_destroy.cc
+++ b/src/starboard/shared/pthread/mutex_destroy.cc
@@ -29,18 +29,18 @@
     return false;
   }
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
   if (!IsInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state))) {
     // If the mutex is not initialized there is nothing to destroy.
     return true;
   }
 #endif
 
-#if SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#if SB_API_VERSION >= 12
   // Both trying to recursively acquire a mutex that is locked by the calling
   // thread, as well as deleting a locked mutex, result in undefined behavior.
   return IsSuccess(pthread_mutex_destroy(SB_PTHREAD_INTERNAL_MUTEX(mutex)));
-#else   // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#else   // SB_API_VERSION >= 12
   // Destroying a locked mutex is undefined, so fail if the mutex is
   // already locked,
   if (!IsSuccess(pthread_mutex_trylock(SB_PTHREAD_INTERNAL_MUTEX(mutex)))) {
@@ -49,5 +49,5 @@
   }
   return IsSuccess(pthread_mutex_unlock(SB_PTHREAD_INTERNAL_MUTEX(mutex))) &&
          IsSuccess(pthread_mutex_destroy(SB_PTHREAD_INTERNAL_MUTEX(mutex)));
-#endif  // SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
+#endif  // SB_API_VERSION >= 12
 }
diff --git a/src/starboard/shared/pthread/mutex_release.cc b/src/starboard/shared/pthread/mutex_release.cc
index 2e9bc41..fcd7de7 100644
--- a/src/starboard/shared/pthread/mutex_release.cc
+++ b/src/starboard/shared/pthread/mutex_release.cc
@@ -27,7 +27,7 @@
     return false;
   }
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
   if (!IsInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state))) {
     // If the mutex is not initialized there is nothing to release.
     return true;
diff --git a/src/starboard/shared/pthread/once.cc b/src/starboard/shared/pthread/once.cc
index c8c937f..e3a898e 100644
--- a/src/starboard/shared/pthread/once.cc
+++ b/src/starboard/shared/pthread/once.cc
@@ -24,7 +24,7 @@
 using starboard::shared::starboard::SetInitialized;
 
 bool SbOnce(SbOnceControl* once_control, SbOnceInitRoutine init_routine) {
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
   SB_COMPILE_ASSERT(sizeof(SbOnceControl) >= sizeof(SbOnceControlPrivate),
                     sb_once_control_private_larger_than_sb_once_control);
 #endif
@@ -34,7 +34,7 @@
   if (init_routine == NULL) {
     return false;
   }
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
   if (!EnsureInitialized(
           &(SB_INTERNAL_ONCE(once_control)->initialized_state))) {
     *SB_PTHREAD_INTERNAL_ONCE(once_control) = PTHREAD_ONCE_INIT;
diff --git a/src/starboard/shared/pthread/thread_context_get_pointer.cc b/src/starboard/shared/pthread/thread_context_get_pointer.cc
index 5baed95..93fc224 100644
--- a/src/starboard/shared/pthread/thread_context_get_pointer.cc
+++ b/src/starboard/shared/pthread/thread_context_get_pointer.cc
@@ -41,11 +41,11 @@
       *out_value = context->fp_;
       return true;
 
-#if SB_API_VERSION >= SB_THREAD_CONTEXT_LINK_REGISTER_VERSION
+#if SB_API_VERSION >= 12
     case kSbThreadContextLinkRegister:
       *out_value = context->lr_;
       return true;
-#endif  // SB_API_VERSION >= SB_THREAD_CONTEXT_LINK_REGISTER_VERSION
+#endif  // SB_API_VERSION >= 12
 
     default:
       SB_NOTIMPLEMENTED() << "SbThreadContextGetPointer not implemented for "
diff --git a/src/starboard/shared/pthread/thread_context_internal.cc b/src/starboard/shared/pthread/thread_context_internal.cc
index 91f06b8..2bf4701 100644
--- a/src/starboard/shared/pthread/thread_context_internal.cc
+++ b/src/starboard/shared/pthread/thread_context_internal.cc
@@ -35,7 +35,7 @@
   mcontext_t& mcontext = ucontext->uc_mcontext;
 
 // TODO: Remove redundant #if checks when
-//       SB_MINIMUM_API_VERSION >= SB_SABI_FILE_VERSION.
+//       SB_MINIMUM_API_VERSION >= 12.
 #if SB_IS_ARCH_X64
   // 64-bit X86 (aka X64)
   ip_ = reinterpret_cast<void*>(mcontext.gregs[REG_RIP]);
diff --git a/src/starboard/shared/pthread/thread_create.cc b/src/starboard/shared/pthread/thread_create.cc
index e470872..96c53f7 100644
--- a/src/starboard/shared/pthread/thread_create.cc
+++ b/src/starboard/shared/pthread/thread_create.cc
@@ -29,11 +29,9 @@
 namespace shared {
 namespace pthread {
 
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION && \
-    !SB_HAS(THREAD_PRIORITY_SUPPORT)
+#if SB_API_VERSION < 12 && !SB_HAS(THREAD_PRIORITY_SUPPORT)
 // Default implementation without thread priority support
-void ThreadSetPriority(SbThreadPriority /* priority */) {
-}
+void ThreadSetPriority(SbThreadPriority priority) {}
 #endif
 
 }  // namespace pthread
diff --git a/src/starboard/shared/pthread/thread_sampler_internal.cc b/src/starboard/shared/pthread/thread_sampler_internal.cc
index fbd66a9..9868a17 100644
--- a/src/starboard/shared/pthread/thread_sampler_internal.cc
+++ b/src/starboard/shared/pthread/thread_sampler_internal.cc
@@ -118,7 +118,6 @@
 
 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
                                          void* context) {
-  SB_UNREFERENCED_PARAMETER(info);
   if (signal != SIGPROF) return;
   sb_context_ = SbThreadContextPrivate(reinterpret_cast<ucontext_t*>(context));
   // |Freeze| can return the context now.
diff --git a/src/starboard/shared/pthread/types_internal.h b/src/starboard/shared/pthread/types_internal.h
index 53100c54..0670baf 100644
--- a/src/starboard/shared/pthread/types_internal.h
+++ b/src/starboard/shared/pthread/types_internal.h
@@ -17,7 +17,7 @@
 #ifndef STARBOARD_SHARED_PTHREAD_TYPES_INTERNAL_H_
 #define STARBOARD_SHARED_PTHREAD_TYPES_INTERNAL_H_
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
 #define SB_INTERNAL_MUTEX(mutex_var) \
   reinterpret_cast<SbMutexPrivate*>((mutex_var)->mutex_buffer)
 #define SB_PTHREAD_INTERNAL_MUTEX(mutex_var) \
@@ -41,7 +41,7 @@
   reinterpret_cast<pthread_t*>(&(thread))
 #define SB_THREAD(thread) (thread)
 #define SB_PTHREAD_INTERNAL_CONDITION(condition_var) (condition_var)
-#endif  // SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#endif  // SB_API_VERSION >= 12
 
 // Transparent Condition Variable handle.
 // It is customized from the plain pthread_cont_t object because we
diff --git a/src/starboard/shared/pthread/types_public.h b/src/starboard/shared/pthread/types_public.h
index 9b82fb4..ebdee71 100644
--- a/src/starboard/shared/pthread/types_public.h
+++ b/src/starboard/shared/pthread/types_public.h
@@ -18,9 +18,9 @@
 #ifndef STARBOARD_SHARED_PTHREAD_TYPES_PUBLIC_H_
 #define STARBOARD_SHARED_PTHREAD_TYPES_PUBLIC_H_
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
 #error "The starboard/shared/pthread/types_public.h is deprecated."
-#endif  // SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #include "starboard/types.h"
 
diff --git a/src/starboard/shared/pulse/pulse_audio_sink_type.cc b/src/starboard/shared/pulse/pulse_audio_sink_type.cc
index 92e763d..5c74442 100644
--- a/src/starboard/shared/pulse/pulse_audio_sink_type.cc
+++ b/src/starboard/shared/pulse/pulse_audio_sink_type.cc
@@ -70,7 +70,7 @@
                  SbAudioSinkFrameBuffers frame_buffers,
                  int frames_per_channel,
                  SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-                 SbAudioSinkConsumeFramesFunc consume_frame_func,
+                 ConsumeFramesFunc consume_frames_func,
                  void* context);
   ~PulseAudioSink() override;
 
@@ -103,7 +103,7 @@
   const uint8_t* const frame_buffer_;
   const int frames_per_channel_;
   const SbAudioSinkUpdateSourceStatusFunc update_source_status_func_;
-  const SbAudioSinkConsumeFramesFunc consume_frame_func_;
+  const ConsumeFramesFunc consume_frames_func_;
   void* const context_;
   const size_t bytes_per_frame_;
 
@@ -131,11 +131,11 @@
       SbAudioSinkFrameBuffers frame_buffers,
       int frames_per_channel,
       SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-      SbAudioSinkConsumeFramesFunc consume_frames_func,
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+      SbAudioSinkPrivate::ConsumeFramesFunc consume_frames_func,
+#if SB_API_VERSION >= 12
       SbAudioSinkPrivate::ErrorFunc error_func,
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
-      void* context);
+#endif  // SB_API_VERSION >= 12
+      void* context) override;
   bool IsValid(SbAudioSink audio_sink) override {
     return audio_sink != kSbAudioSinkInvalid && audio_sink->IsType(this);
   }
@@ -175,7 +175,7 @@
     SbAudioSinkFrameBuffers frame_buffers,
     int frames_per_channel,
     SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-    SbAudioSinkConsumeFramesFunc consume_frame_func,
+    ConsumeFramesFunc consume_frames_func,
     void* context)
     : type_(type),
       channels_(channels),
@@ -184,12 +184,12 @@
       frame_buffer_(static_cast<uint8_t*>(frame_buffers[0])),
       frames_per_channel_(frames_per_channel),
       update_source_status_func_(update_source_status_func),
-      consume_frame_func_(consume_frame_func),
+      consume_frames_func_(consume_frames_func),
       context_(context),
       bytes_per_frame_(static_cast<size_t>(channels) *
                        GetBytesPerSample(sample_type)) {
   SB_DCHECK(update_source_status_func_);
-  SB_DCHECK(consume_frame_func_);
+  SB_DCHECK(consume_frames_func_);
   SB_DCHECK(frame_buffer_);
   SB_DCHECK(SbAudioSinkIsAudioSampleTypeSupported(sample_type_));
 }
@@ -278,12 +278,7 @@
       SB_DCHECK(total_frames_played_ <= new_total_frames_played);
       int64_t consume = new_total_frames_played - total_frames_played_;
       if (consume > 0) {
-        consume_frame_func_(
-            consume,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-            (SbTime)kSbTimeMax,  // Async audio frames reporting not supported
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-            context_);
+        consume_frames_func_(consume, SbTimeGetMonotonicNow(), context_);
         total_frames_played_ = new_total_frames_played;
       }
     }
@@ -403,10 +398,10 @@
     SbAudioSinkFrameBuffers frame_buffers,
     int frames_per_channel,
     SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-    SbAudioSinkConsumeFramesFunc consume_frames_func,
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+    SbAudioSinkPrivate::ConsumeFramesFunc consume_frames_func,
+#if SB_API_VERSION >= 12
     SbAudioSinkPrivate::ErrorFunc error_func,
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#endif  // SB_API_VERSION >= 12
     void* context) {
   PulseAudioSink* audio_sink = new PulseAudioSink(
       this, channels, sampling_frequency_hz, audio_sample_type, frame_buffers,
diff --git a/src/starboard/shared/signal/signal_internal.h b/src/starboard/shared/signal/signal_internal.h
index 57dff5e..8277128 100644
--- a/src/starboard/shared/signal/signal_internal.h
+++ b/src/starboard/shared/signal/signal_internal.h
@@ -42,6 +42,8 @@
       return "SIGINT";
     case SIGPIPE:
       return "SIGPIPE";
+    case SIGPWR:
+      return "SIGPWR";
     case SIGQUIT:
       return "SIGQUIT";
     case SIGSEGV:
diff --git a/src/starboard/shared/signal/suspend_signals.cc b/src/starboard/shared/signal/suspend_signals.cc
index d5a0ace..e81dcc6 100644
--- a/src/starboard/shared/signal/suspend_signals.cc
+++ b/src/starboard/shared/signal/suspend_signals.cc
@@ -31,7 +31,8 @@
 
 namespace {
 
-const std::initializer_list<int> kAllSignals = {SIGUSR1, SIGUSR2, SIGCONT};
+const std::initializer_list<int> kAllSignals = {SIGUSR1, SIGUSR2, SIGCONT,
+                                                SIGTSTP, SIGPWR};
 
 int SignalMask(std::initializer_list<int> signal_ids, int action) {
   sigset_t mask;
@@ -54,6 +55,37 @@
   ::sigaction(signal_id, &action, NULL);
 }
 
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void Conceal(int signal_id) {
+  SignalMask(kAllSignals, SIG_BLOCK);
+  LogSignalCaught(signal_id);
+  SbSystemRequestConceal();
+  SignalMask(kAllSignals, SIG_UNBLOCK);
+}
+
+void Focus(int signal_id) {
+  SignalMask(kAllSignals, SIG_BLOCK);
+  LogSignalCaught(signal_id);
+  // TODO: Unfreeze or Focus based on state before frozen?
+  starboard::Application::Get()->Focus(NULL, NULL);
+  SignalMask(kAllSignals, SIG_UNBLOCK);
+}
+
+void Freeze(int signal_id) {
+  SignalMask(kAllSignals, SIG_BLOCK);
+  LogSignalCaught(signal_id);
+  SbSystemRequestFreeze();
+  SignalMask(kAllSignals, SIG_UNBLOCK);
+}
+
+void Stop(int signal_id) {
+  SignalMask(kAllSignals, SIG_BLOCK);
+  LogSignalCaught(signal_id);
+  starboard::Application::Get()->Stop(0);
+  SignalMask(kAllSignals, SIG_UNBLOCK);
+}
+#else
 void Suspend(int signal_id) {
   SignalMask(kAllSignals, SIG_BLOCK);
   LogSignalCaught(signal_id);
@@ -68,6 +100,8 @@
   starboard::Application::Get()->Unpause(NULL, NULL);
   SignalMask(kAllSignals, SIG_UNBLOCK);
 }
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
 
 void LowMemory(int signal_id) {
   SignalMask(kAllSignals, SIG_BLOCK);
@@ -125,10 +159,22 @@
   // Future created threads inherit the same block mask as per POSIX rules
   // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html
   SignalMask(kAllSignals, SIG_BLOCK);
+
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+  SetSignalHandler(SIGUSR1, &Conceal);
+  SetSignalHandler(SIGUSR2, &LowMemory);
+  SetSignalHandler(SIGCONT, &Focus);
+  SetSignalHandler(SIGTSTP, &Freeze);
+  SetSignalHandler(SIGPWR, &Stop);
+  ConfigureSignalHandlerThread(true);
+#else
   SetSignalHandler(SIGUSR1, &Suspend);
   SetSignalHandler(SIGUSR2, &LowMemory);
   SetSignalHandler(SIGCONT, &Resume);
   ConfigureSignalHandlerThread(true);
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
 }
 
 void UninstallSuspendSignalHandlers() {
@@ -138,9 +184,14 @@
   SetSignalHandler(SIGUSR1, SIG_DFL);
   SetSignalHandler(SIGUSR2, SIG_DFL);
   SetSignalHandler(SIGCONT, SIG_DFL);
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+  SetSignalHandler(SIGPWR, SIG_DFL);
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
   ConfigureSignalHandlerThread(false);
 }
 
 }  // namespace signal
 }  // namespace shared
-}  // namespace starboard
+}  // namespace starboard
\ No newline at end of file
diff --git a/src/starboard/shared/signal/system_request_conceal.cc b/src/starboard/shared/signal/system_request_conceal.cc
new file mode 100644
index 0000000..0208148
--- /dev/null
+++ b/src/starboard/shared/signal/system_request_conceal.cc
@@ -0,0 +1,25 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "starboard/shared/starboard/application.h"
+
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void SbSystemRequestConceal() {
+  starboard::shared::starboard::Application::Get()->Conceal(NULL, NULL);
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/signal/system_request_freeze.cc b/src/starboard/shared/signal/system_request_freeze.cc
new file mode 100644
index 0000000..bfadf43
--- /dev/null
+++ b/src/starboard/shared/signal/system_request_freeze.cc
@@ -0,0 +1,32 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "starboard/shared/signal/signal_internal.h"
+#include "starboard/shared/starboard/application.h"
+
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void FreezeDone(void* /*context*/) {
+  // Stop all thread execution after fully transitioning into Frozen.
+  raise(SIGSTOP);
+}
+
+void SbSystemRequestFreeze() {
+  // Let the platform decide if directly transit into Frozen.
+  starboard::shared::starboard::Application::Get()->Freeze(NULL, &FreezeDone);
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/signal/system_request_suspend.cc b/src/starboard/shared/signal/system_request_suspend.cc
index a663bc9..e3977d9 100644
--- a/src/starboard/shared/signal/system_request_suspend.cc
+++ b/src/starboard/shared/signal/system_request_suspend.cc
@@ -17,6 +17,8 @@
 #include "starboard/shared/signal/signal_internal.h"
 #include "starboard/shared/starboard/application.h"
 
+#if SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION && \
+    !SB_HAS(CONCEALED_STATE)
 void SuspendDone(void* /*context*/) {
   // Stop all thread execution after fully transitioning into Suspended.
   raise(SIGSTOP);
@@ -25,3 +27,5 @@
 void SbSystemRequestSuspend() {
   starboard::shared::starboard::Application::Get()->Suspend(NULL, &SuspendDone);
 }
+#endif  // SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION &&
+        // !SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/speechd/speech_synthesis_is_supported.cc b/src/starboard/shared/speechd/speech_synthesis_is_supported.cc
index 1364fbc..ee7f1be 100644
--- a/src/starboard/shared/speechd/speech_synthesis_is_supported.cc
+++ b/src/starboard/shared/speechd/speech_synthesis_is_supported.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/speech_synthesis.h"
 
-#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbSpeechSynthesisIsSupported() {
   return true;
diff --git a/src/starboard/shared/starboard/application.cc b/src/starboard/shared/starboard/application.cc
index 9c724c3..adb3065 100644
--- a/src/starboard/shared/starboard/application.cc
+++ b/src/starboard/shared/starboard/application.cc
@@ -76,7 +76,6 @@
           reinterpret_cast<SbAtomicPtr>(reinterpret_cast<void*>(NULL)),
           reinterpret_cast<SbAtomicPtr>(this)));
   SB_DCHECK(!old_instance);
-  SB_UNREFERENCED_PARAMETER(old_instance);
 }
 
 Application::~Application() {
@@ -126,6 +125,33 @@
   return command_line_.get();
 }
 
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void Application::Blur(void* context, EventHandledCallback callback) {
+  Inject(new Event(kSbEventTypeBlur, context, callback));
+}
+
+void Application::Focus(void* context, EventHandledCallback callback) {
+  Inject(new Event(kSbEventTypeFocus, context, callback));
+}
+
+void Application::Conceal(void* context, EventHandledCallback callback) {
+  Inject(new Event(kSbEventTypeConceal, context, callback));
+}
+
+void Application::Reveal(void* context, EventHandledCallback callback) {
+  Inject(new Event(kSbEventTypeReveal, context, callback));
+}
+
+void Application::Freeze(void* context, EventHandledCallback callback) {
+  Inject(new Event(kSbEventTypeFreeze, context, callback));
+}
+
+void Application::Unfreeze(void* context, EventHandledCallback callback) {
+  Inject(new Event(kSbEventTypeUnfreeze, context, callback));
+}
+
+#else
 void Application::Pause(void* context, EventHandledCallback callback) {
   Inject(new Event(kSbEventTypePause, context, callback));
 }
@@ -141,6 +167,8 @@
 void Application::Resume(void* context, EventHandledCallback callback) {
   Inject(new Event(kSbEventTypeResume, context, callback));
 }
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
 
 void Application::Stop(int error_level) {
   Event* event = new Event(kSbEventTypeStop, NULL, NULL);
@@ -199,7 +227,13 @@
 
 void Application::DispatchStart() {
   SB_DCHECK(IsCurrentThread());
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+  SB_DCHECK(state_ == kStateUnstarted);
+#else
   SB_DCHECK(state_ == kStateUnstarted || state_ == kStatePreloading);
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
   DispatchAndDelete(CreateInitialEvent(kSbEventTypeStart));
 }
 
@@ -222,6 +256,139 @@
   // Ensure the event is deleted unless it is released.
   scoped_ptr<Event> scoped_event(event);
 
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+  // Ensure that we go through the the appropriate lifecycle events based on the
+  // current state.
+  switch (scoped_event->event->type) {
+    case kSbEventTypePreload:
+      if (state() != kStateUnstarted) {
+        return true;
+      }
+      break;
+    case kSbEventTypeStart:
+      if (state() != kStateUnstarted && state() != kStateStarted) {
+        Inject(new Event(kSbEventTypeFocus, NULL, NULL));
+        return true;
+      }
+      break;
+    case kSbEventTypeBlur:
+      if (state() != kStateStarted) {
+        return true;
+      }
+      break;
+    case kSbEventTypeFocus:
+      switch (state()) {
+        case kStateStopped:
+          return true;
+        case kStateFrozen:
+          Inject(new Event(kSbEventTypeUnfreeze, NULL, NULL));
+          // The fall-through is intentional.
+        case kStateConcealed:
+          Inject(new Event(kSbEventTypeReveal, NULL, NULL));
+          Inject(scoped_event.release());
+          return true;
+        case kStateBlurred:
+          break;
+        case kStateStarted:
+        case kStateUnstarted:
+          return true;
+      }
+      break;
+    case kSbEventTypeConceal:
+      switch (state()) {
+        case kStateUnstarted:
+          return true;
+        case kStateStarted:
+          Inject(new Event(kSbEventTypeBlur, NULL, NULL));
+          Inject(scoped_event.release());
+          return true;
+        case kStateBlurred:
+          break;
+        case kStateConcealed:
+        case kStateFrozen:
+        case kStateStopped:
+          return true;
+      }
+      break;
+    case kSbEventTypeReveal:
+      switch (state()) {
+        case kStateStopped:
+          return true;
+        case kStateFrozen:
+          Inject(new Event(kSbEventTypeUnfreeze, NULL, NULL));
+          Inject(scoped_event.release());
+          return true;
+        case kStateConcealed:
+          break;
+        case kStateBlurred:
+        case kStateStarted:
+        case kStateUnstarted:
+          return true;
+      }
+      break;
+    case kSbEventTypeFreeze:
+      switch (state()) {
+        case kStateUnstarted:
+          return true;
+        case kStateStarted:
+          Inject(new Event(kSbEventTypeBlur, NULL, NULL));
+          // The fall-through is intentional
+        case kStateBlurred:
+          Inject(new Event(kSbEventTypeConceal, NULL, NULL));
+          Inject(scoped_event.release());
+          return true;
+        case kStateConcealed:
+          break;
+        case kStateFrozen:
+        case kStateStopped:
+          return true;
+      }
+      break;
+    case kSbEventTypeUnfreeze:
+      switch (state()) {
+        case kStateStopped:
+          return true;
+        case kStateFrozen:
+          break;
+        case kStateConcealed:
+        case kStateBlurred:
+        case kStateStarted:
+        case kStateUnstarted:
+          return true;
+      }
+      break;
+    case kSbEventTypeStop:
+      switch (state()) {
+        case kStateUnstarted:
+          return true;
+        case kStateStarted:
+          Inject(new Event(kSbEventTypeBlur, NULL, NULL));
+          // The fall-through is intentional.
+        case kStateBlurred:
+          Inject(new Event(kSbEventTypeConceal, NULL, NULL));
+          // The fall-through is intentional.
+        case kStateConcealed:
+          Inject(new Event(kSbEventTypeFreeze, NULL, NULL));
+          Inject(scoped_event.release());
+          return true;
+        case kStateFrozen:
+          break;
+        case kStateStopped:
+          return true;
+      }
+      error_level_ = scoped_event->error_level;
+      break;
+    case kSbEventTypeScheduled: {
+      TimedEvent* timed_event =
+          reinterpret_cast<TimedEvent*>(scoped_event->event->data);
+      timed_event->callback(timed_event->context);
+      return true;
+    }
+    default:
+      break;
+  }
+#else
   // Ensure that we go through the the appropriate lifecycle events based on the
   // current state.
   switch (scoped_event->event->type) {
@@ -306,9 +473,54 @@
     default:
       break;
   }
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
 
   SbEventHandle(scoped_event->event);
-
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+  switch (scoped_event->event->type) {
+    case kSbEventTypePreload:
+      SB_DCHECK(state() == kStateUnstarted);
+      state_ = kStateConcealed;
+      break;
+    case kSbEventTypeStart:
+      SB_DCHECK(state() == kStateUnstarted);
+      state_ = kStateStarted;
+      break;
+    case kSbEventTypeBlur:
+      SB_DCHECK(state() == kStateStarted);
+      state_ = kStateBlurred;
+      break;
+    case kSbEventTypeFocus:
+      SB_DCHECK(state() == kStateBlurred);
+      state_ = kStateStarted;
+      break;
+    case kSbEventTypeConceal:
+      SB_DCHECK(state() == kStateBlurred);
+      state_ = kStateConcealed;
+      break;
+    case kSbEventTypeReveal:
+      SB_DCHECK(state() == kStateConcealed);
+      state_ = kStateBlurred;
+      break;
+    case kSbEventTypeFreeze:
+      SB_DCHECK(state() == kStateConcealed);
+      state_ = kStateFrozen;
+      OnSuspend();
+      break;
+    case kSbEventTypeUnfreeze:
+      SB_DCHECK(state() == kStateFrozen);
+      state_ = kStateConcealed;
+      break;
+    case kSbEventTypeStop:
+      SB_DCHECK(state() == kStateFrozen);
+      state_ = kStateStopped;
+      return false;
+    default:
+      break;
+  }
+#else
   switch (scoped_event->event->type) {
     case kSbEventTypePreload:
       SB_DCHECK(state() == kStateUnstarted);
@@ -342,7 +554,8 @@
     default:
       break;
   }
-
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
   // Should not be unstarted after the first event.
   SB_DCHECK(state() != kStateUnstarted);
   return true;
diff --git a/src/starboard/shared/starboard/application.h b/src/starboard/shared/starboard/application.h
index 8778deb..f8945af 100644
--- a/src/starboard/shared/starboard/application.h
+++ b/src/starboard/shared/starboard/application.h
@@ -52,6 +52,34 @@
   // Signature for a function that will be called at the beginning of Teardown.
   typedef void (*TeardownCallback)(void);
 
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+  // Enumeration of states that the application can be in.
+  enum State {
+    // The initial Unstarted state.
+    kStateUnstarted,
+
+    // The normal foreground, fully-visible state after receiving the initial
+    // START event or after FOCUS from Blurred.
+    kStateStarted,
+
+    // The background-but-visible or partially-obscured state after receiving a
+    // BLUR event from Started or REVEAL event from Concealed.
+    kStateBlurred,
+
+    // The background-invisible state after receving a CONCEAL event from
+    // Blurred or UNFREEZE event from Frozen.
+    kStateConcealed,
+
+    // The fully-obscured or about-to-be-terminated state after receiving a
+    // FREEZE event in Concealed.
+    kStateFrozen,
+
+    // The completely terminated state after receiving the STOP event in the
+    // Frozen.
+    kStateStopped,
+  };
+#else
   // Enumeration of states that the application can be in.
   enum State {
     // The initial Unstarted state.
@@ -78,6 +106,8 @@
     // Suspended state.
     kStateStopped,
   };
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
 
   // Structure to keep track of scheduled events, also used as the data argument
   // for kSbEventTypeScheduled Events.
@@ -176,6 +206,72 @@
   // NULL until Run() is called.
   const CommandLine* GetCommandLine();
 
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+  // Signals that the application should transition from STARTED to BLURRED as
+  // soon as possible. Does nothing if already BLURRED or CONCEALED. May be
+  // called from an external thread.
+  //
+  // |context|: A context value to pass to |callback| on event completion. Must
+  // not be NULL if callback is not NULL.
+  // |callback|: A function to call on event completion, from the main thread.
+  void Blur(void* context, EventHandledCallback callback);
+
+  // Signals that the application should transition to STARTED as soon as
+  // possible, moving through all required state transitions to get there. Does
+  // nothing if already STARTED. May be called from an external thread.
+  //
+  // |context|: A context value to pass to |callback| on event completion. Must
+  // not be NULL if callback is not NULL.
+  // |callback|: A function to call on event completion, from the main thread.
+  void Focus(void* context, EventHandledCallback callback);
+
+  // Signals that the application should transition to CONCEALED from BLURRED
+  // as soon as possible, moving through all required state transitions to get
+  // there. Does nothing if already CONCEALED, FROZEN, or STOPPED. May be called
+  // from an external thread.
+  //
+  // |context|: A context value to pass to |callback| on event completion. Must
+  // not be NULL if callback is not NULL.
+  // |callback|: A function to call on event completion, from the main thread.
+  void Conceal(void* context, EventHandledCallback callback);
+
+  // Signals that the application should transition to BLURRED from CONCEALED as
+  // soon as possible, moving through all required state transitions to get
+  // there. Does nothing if already STARTED or BLURRED. May be called from
+  // an external thread.
+  //
+  // |context|: A context value to pass to |callback| on event completion. Must
+  // not be NULL if callback is not NULL.
+  // |callback|: A function to call on event completion, from the main thread.
+  void Reveal(void* context, EventHandledCallback callback);
+
+  // Signals that the application should transition to FROZEN as soon as
+  // possible, moving through all required state transitions to get there. Does
+  // nothing if already FROZEN or STOPPED. May be called from an external
+  // thread.
+  //
+  // |context|: A context value to pass to |callback| on event completion. Must
+  // not be NULL if callback is not NULL.
+  // |callback|: A function to call on event completion, from the main thread.
+  void Freeze(void* context, EventHandledCallback callback);
+
+  // Signals that the application should transition to CONCEALED from FROZEN as
+  // soon as possible. Does nothing if already CONCEALED, BLURRED, or STARTED.
+  // May be called from an external thread.
+  //
+  // |context|: A context value to pass to |callback| on event completion. Must
+  // not be NULL if callback is not NULL.
+  // |callback|: A function to call on event completion, from the main thread.
+  void Unfreeze(void* context, EventHandledCallback callback);
+
+  // Signals that the application should gracefully terminate as soon as
+  // possible. Will transition through BLURRED, CONCEALED and FROZEN to STOPPED
+  // as appropriate for the current state. May be called from an external
+  // thread.
+  void Stop(int error_level);
+
+#else
   // Signals that the application should transition from STARTED to PAUSED as
   // soon as possible. Does nothing if already PAUSED or SUSPENDED. May be
   // called from an external thread.
@@ -216,6 +312,8 @@
   // possible. Will transition through PAUSED and SUSPENDED to STOPPED as
   // appropriate for the current state. May be called from an external thread.
   void Stop(int error_level);
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
 
   // Injects a link event to the application with the given |link_data|, which
   // must be a null-terminated string. Makes a copy of |link_data|, so it only
@@ -284,13 +382,13 @@
 
   // Subclasses may override this method to accept video frames from the media
   // system. Will be called from an external thread.
-  virtual void AcceptFrame(SbPlayer /* player */,
-                           const scoped_refptr<VideoFrame>& /* frame */,
-                           int /* z_index */,
-                           int /* x */,
-                           int /* y */,
-                           int /* width */,
-                           int /* height */) {}
+  virtual void AcceptFrame(SbPlayer player,
+                           const scoped_refptr<VideoFrame>& frame,
+                           int z_index,
+                           int x,
+                           int y,
+                           int width,
+                           int height) {}
 
   // Blocks until the next event is available. Subclasses must implement this
   // method to provide events for the platform. Gives ownership to the caller.
diff --git a/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc b/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc
index bcddf3b..dd9d555 100644
--- a/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc
+++ b/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc
@@ -75,13 +75,15 @@
     SB_LOG(WARNING) << "Preferred Sink Type is invalid.";
     return kSbAudioSinkInvalid;
   }
+
   SbAudioSink audio_sink = audio_sink_type->Create(
       channels, sampling_frequency_hz, audio_sample_type,
       audio_frame_storage_type, frame_buffers, frame_buffers_size_in_frames,
-      update_source_status_func, consume_frames_func,
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+      update_source_status_func,
+      SbAudioSinkPrivate::GetConsumeFramesFunc(consume_frames_func),
+#if SB_API_VERSION >= 12
       NULL /*error_func*/,
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#endif  // SB_API_VERSION >= 12
       context);
   if (audio_sink_type->IsValid(audio_sink)) {
     return audio_sink;
@@ -95,10 +97,11 @@
   audio_sink = fallback_audio_sink_type->Create(
       channels, sampling_frequency_hz, audio_sample_type,
       audio_frame_storage_type, frame_buffers, frame_buffers_size_in_frames,
-      update_source_status_func, consume_frames_func,
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+      update_source_status_func,
+      SbAudioSinkPrivate::GetConsumeFramesFunc(consume_frames_func),
+#if SB_API_VERSION >= 12
       NULL /*error_func*/,
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#endif  // SB_API_VERSION >= 12
       context);
   if (fallback_audio_sink_type->IsValid(audio_sink)) {
     return audio_sink;
diff --git a/src/starboard/shared/starboard/audio_sink/audio_sink_get_min_buffer_size_in_frames.cc b/src/starboard/shared/starboard/audio_sink/audio_sink_get_min_buffer_size_in_frames.cc
index 89e6f39..e8b8b89 100644
--- a/src/starboard/shared/starboard/audio_sink/audio_sink_get_min_buffer_size_in_frames.cc
+++ b/src/starboard/shared/starboard/audio_sink/audio_sink_get_min_buffer_size_in_frames.cc
@@ -34,8 +34,8 @@
   }
   // Larger buffer size would have more latency when changing playback rate.
   if (sampling_frequency_hz < 24000) {
-    return 4 * 1024;
+    return 3 * 1024;
   }
 
-  return 8 * 1024;
+  return 5 * 1024;
 }
diff --git a/src/starboard/shared/starboard/audio_sink/audio_sink_internal.cc b/src/starboard/shared/starboard/audio_sink/audio_sink_internal.cc
index 6614fea..a3f4f08 100644
--- a/src/starboard/shared/starboard/audio_sink/audio_sink_internal.cc
+++ b/src/starboard/shared/starboard/audio_sink/audio_sink_internal.cc
@@ -14,12 +14,18 @@
 
 #include "starboard/shared/starboard/audio_sink/audio_sink_internal.h"
 
+#include <functional>
+
 #include "starboard/shared/starboard/application.h"
 #include "starboard/shared/starboard/audio_sink/stub_audio_sink_type.h"
 #include "starboard/shared/starboard/command_line.h"
 
 namespace {
 
+using std::placeholders::_1;
+using std::placeholders::_2;
+using std::placeholders::_3;
+
 bool is_fallback_to_stub_enabled;
 SbAudioSinkPrivate::Type* primary_audio_sink_type;
 SbAudioSinkPrivate::Type* fallback_audio_sink_type;
@@ -28,6 +34,22 @@
 // even when the primary audio sink may be available.
 const char kUseStubAudioSink[] = "use_stub_audio_sink";
 
+void WrapConsumeFramesFunc(SbAudioSinkConsumeFramesFunc sb_consume_frames_func,
+                           int frames_consumed,
+                           SbTime frames_consumed_at,
+                           void* context) {
+#if SB_API_VERSION >= 12
+  SB_UNREFERENCED_PARAMETER(frames_consumed_at);
+  sb_consume_frames_func(frames_consumed, context);
+#else  // SB_API_VERSION >= 12
+  sb_consume_frames_func(frames_consumed,
+#if SB_HAS(SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING)
+                         frames_consumed_at,
+#endif
+                         context);
+#endif  // SB_API_VERSION >=  12
+}
+
 }  // namespace
 
 using starboard::shared::starboard::audio_sink::StubAudioSinkType;
@@ -84,3 +106,10 @@
   }
   return audio_sink_type;
 }
+
+// static
+SbAudioSinkPrivate::ConsumeFramesFunc SbAudioSinkPrivate::GetConsumeFramesFunc(
+    SbAudioSinkConsumeFramesFunc sb_consume_frames_func) {
+  return std::bind(&::WrapConsumeFramesFunc, sb_consume_frames_func, _1, _2,
+                   _3);
+}
diff --git a/src/starboard/shared/starboard/audio_sink/audio_sink_internal.h b/src/starboard/shared/starboard/audio_sink/audio_sink_internal.h
index 28bcec2..322ea45 100644
--- a/src/starboard/shared/starboard/audio_sink/audio_sink_internal.h
+++ b/src/starboard/shared/starboard/audio_sink/audio_sink_internal.h
@@ -16,16 +16,23 @@
 #define STARBOARD_SHARED_STARBOARD_AUDIO_SINK_AUDIO_SINK_INTERNAL_H_
 
 #include "starboard/audio_sink.h"
+
+#include <functional>
+
 #include "starboard/configuration.h"
 #include "starboard/shared/internal_only.h"
 
 struct SbAudioSinkPrivate {
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#if SB_API_VERSION >= 12
   // When |capability_changed| is true, it hints that the error is caused by a
   // a transisent capability on the platform.  The app should retry playback to
   // recover from the error.
   typedef void (*ErrorFunc)(bool capability_changed, void* context);
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#endif  // SB_API_VERSION >= 12
+
+  typedef std::function<
+      void(int frames_consumed, SbTime frames_consumed_at, void* context)>
+      ConsumeFramesFunc;
 
   class Type {
    public:
@@ -40,10 +47,10 @@
         SbAudioSinkFrameBuffers frame_buffers,
         int frame_buffers_size_in_frames,
         SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-        SbAudioSinkConsumeFramesFunc consume_frames_func,
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+        ConsumeFramesFunc consume_frames_func,
+#if SB_API_VERSION >= 12
         ErrorFunc error_func,
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#endif  // SB_API_VERSION >= 12
         void* context) = 0;
     virtual bool IsValid(SbAudioSink audio_sink) = 0;
     virtual void Destroy(SbAudioSink audio_sink) = 0;
@@ -80,6 +87,9 @@
   // functions, which will be called inside Initialize() and TearDown().
   static void PlatformInitialize();
   static void PlatformTearDown();
+
+  static ConsumeFramesFunc GetConsumeFramesFunc(
+      SbAudioSinkConsumeFramesFunc sb_consume_frames_func);
 };
 
 #endif  // STARBOARD_SHARED_STARBOARD_AUDIO_SINK_AUDIO_SINK_INTERNAL_H_
diff --git a/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc b/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc
index 36fc9db..e82d6b8 100644
--- a/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc
+++ b/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc
@@ -33,18 +33,16 @@
   StubAudioSink(Type* type,
                 int sampling_frequency_hz,
                 SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-                SbAudioSinkConsumeFramesFunc consume_frame_func,
+                ConsumeFramesFunc consume_frames_func,
                 void* context);
   ~StubAudioSink() override;
 
   bool IsType(Type* type) override { return type_ == type; }
   void SetPlaybackRate(double playback_rate) override {
-    SB_UNREFERENCED_PARAMETER(playback_rate);
     SB_NOTIMPLEMENTED();
   }
 
   void SetVolume(double volume) override {
-    SB_UNREFERENCED_PARAMETER(volume);
   }
 
  private:
@@ -53,7 +51,7 @@
 
   Type* type_;
   SbAudioSinkUpdateSourceStatusFunc update_source_status_func_;
-  SbAudioSinkConsumeFramesFunc consume_frame_func_;
+  ConsumeFramesFunc consume_frames_func_;
   void* context_;
 
   int sampling_frequency_hz_;
@@ -68,12 +66,12 @@
     Type* type,
     int sampling_frequency_hz,
     SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-    SbAudioSinkConsumeFramesFunc consume_frame_func,
+    ConsumeFramesFunc consume_frames_func,
     void* context)
     : type_(type),
       sampling_frequency_hz_(sampling_frequency_hz),
       update_source_status_func_(update_source_status_func),
-      consume_frame_func_(consume_frame_func),
+      consume_frames_func_(consume_frames_func),
       context_(context),
       audio_out_thread_(kSbThreadInvalid),
       destroying_(false) {
@@ -119,15 +117,8 @@
           std::min(kMaxFramesToConsumePerRequest, frames_in_buffer);
 
       SbThreadSleep(frames_to_consume * kSbTimeSecond / sampling_frequency_hz_);
-      consume_frame_func_(frames_to_consume,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-                          kSbHasAsyncAudioFramesReporting
-                              ? SbTimeGetMonotonicNow()
-                              : (SbTime)kSbTimeMax,
-#elif SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-                          SbTimeGetMonotonicNow(),
-#endif
-                          context_);
+      consume_frames_func_(frames_to_consume, SbTimeGetMonotonicNow(),
+                           context_);
     } else {
       // Wait for five millisecond if we are paused.
       SbThreadSleep(kSbTimeMillisecond * 5);
@@ -145,16 +136,11 @@
     SbAudioSinkFrameBuffers frame_buffers,
     int frame_buffers_size_in_frames,
     SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-    SbAudioSinkConsumeFramesFunc consume_frames_func,
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+    SbAudioSinkPrivate::ConsumeFramesFunc consume_frames_func,
+#if SB_API_VERSION >= 12
     SbAudioSinkPrivate::ErrorFunc error_func,
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#endif  // SB_API_VERSION >= 12
     void* context) {
-  SB_UNREFERENCED_PARAMETER(audio_frame_storage_type);
-  SB_UNREFERENCED_PARAMETER(audio_sample_type);
-  SB_UNREFERENCED_PARAMETER(channels);
-  SB_UNREFERENCED_PARAMETER(frame_buffers_size_in_frames);
-  SB_UNREFERENCED_PARAMETER(frame_buffers);
 
   return new StubAudioSink(this, sampling_frequency_hz,
                            update_source_status_func, consume_frames_func,
diff --git a/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.h b/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.h
index 1c471a4..7ee89a8 100644
--- a/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.h
+++ b/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.h
@@ -34,11 +34,11 @@
       SbAudioSinkFrameBuffers frame_buffers,
       int frame_buffers_size_in_frames,
       SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
-      SbAudioSinkConsumeFramesFunc consume_frames_func,
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+      SbAudioSinkPrivate::ConsumeFramesFunc consume_frames_func,
+#if SB_API_VERSION >= 12
       SbAudioSinkPrivate::ErrorFunc error_func,
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
-      void* context);
+#endif  // SB_API_VERSION >= 12
+      void* context) override;
 
   bool IsValid(SbAudioSink audio_sink) override {
     return audio_sink != kSbAudioSinkInvalid && audio_sink->IsType(this);
diff --git a/src/starboard/shared/starboard/command_line.cc b/src/starboard/shared/starboard/command_line.cc
index 851783b..ad19ccf 100644
--- a/src/starboard/shared/starboard/command_line.cc
+++ b/src/starboard/shared/starboard/command_line.cc
@@ -176,7 +176,6 @@
 
 void CommandLine::AppendArguments(const CommandLine& other,
                                   bool include_program) {
-  SB_UNREFERENCED_PARAMETER(include_program);
   AppendSwitchesAndArguments(this, other.argv());
 }
 
diff --git a/src/starboard/shared/starboard/configuration_constants_compatibility_defines.h b/src/starboard/shared/starboard/configuration_constants_compatibility_defines.h
index 5af45c9..0952566 100644
--- a/src/starboard/shared/starboard/configuration_constants_compatibility_defines.h
+++ b/src/starboard/shared/starboard/configuration_constants_compatibility_defines.h
@@ -19,13 +19,13 @@
 #ifndef STARBOARD_SHARED_STARBOARD_CONFIGURATION_CONSTANTS_COMPATIBILITY_DEFINES_H_
 #define STARBOARD_SHARED_STARBOARD_CONFIGURATION_CONSTANTS_COMPATIBILITY_DEFINES_H_
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
 
 #error \
     "This file is only relevant for Starboard versions before 12. Please do " \
 "not include this file otherwise."
 
-#else  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else  // SB_API_VERSION >= 12
 
 #define kSbDefaultMmapThreshold SB_DEFAULT_MMAP_THRESHOLD
 
@@ -45,8 +45,6 @@
 
 #define kSbHasAc3Audio SB_HAS_AC3_AUDIO
 
-#define kSbHasAsyncAudioFramesReporting SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING
-
 #define kSbHasMediaWebmVp9Support SB_HAS_MEDIA_WEBM_VP9_SUPPORT
 
 #define kSbHasThreadPrioritySupport SB_HAS_THREAD_PRIORITY_SUPPORT
@@ -85,6 +83,6 @@
 
 #define kSbUserMaxSignedIn SB_USER_MAX_SIGNED_IN
 
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #endif  // STARBOARD_SHARED_STARBOARD_CONFIGURATION_CONSTANTS_COMPATIBILITY_DEFINES_H_
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc b/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc
index 9845a42..900678a 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/common/log.h"
 #include "starboard/common/string.h"
@@ -123,4 +123,4 @@
   return transformer;
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_destroy_transformer.cc b/src/starboard/shared/starboard/cryptography/cryptography_destroy_transformer.cc
index c3e68c5..f87e2ed 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_destroy_transformer.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_destroy_transformer.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 #include "starboard/shared/starboard/cryptography/cryptography_internal.h"
@@ -27,4 +27,4 @@
   delete transformer;
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_get_tag.cc b/src/starboard/shared/starboard/cryptography/cryptography_get_tag.cc
index 20dacd3..9b19b98 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_get_tag.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_get_tag.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 #include "starboard/shared/starboard/cryptography/cryptography_internal.h"
@@ -36,4 +36,4 @@
   return true;
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_internal.h b/src/starboard/shared/starboard/cryptography/cryptography_internal.h
index 4a5ffa2..8b00947 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_internal.h
+++ b/src/starboard/shared/starboard/cryptography/cryptography_internal.h
@@ -15,7 +15,7 @@
 #ifndef STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_CRYPTOGRAPHY_INTERNAL_H_
 #define STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_CRYPTOGRAPHY_INTERNAL_H_
 
-#if SB_API_VERSION >= SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION >= 12
 #error "Starboard Crypto API is deprecated"
 #else
 
@@ -52,6 +52,6 @@
   uint32_t counter;
 };
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #endif  // STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_CRYPTOGRAPHY_INTERNAL_H_
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_set_authenticated_data.cc b/src/starboard/shared/starboard/cryptography/cryptography_set_authenticated_data.cc
index 7af5fce..e8c973f 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_set_authenticated_data.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_set_authenticated_data.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 #include "starboard/shared/starboard/cryptography/cryptography_internal.h"
@@ -36,4 +36,4 @@
   return result == 1;
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_set_initialization_vector.cc b/src/starboard/shared/starboard/cryptography/cryptography_set_initialization_vector.cc
index 8c70ae0..f700be9 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_set_initialization_vector.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_set_initialization_vector.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 
@@ -42,4 +42,4 @@
   }
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_transform.cc b/src/starboard/shared/starboard/cryptography/cryptography_transform.cc
index 8a84ee0..ed464a2 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_transform.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_transform.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 #include "starboard/shared/starboard/cryptography/cryptography_internal.h"
@@ -114,4 +114,4 @@
   return in_data_size;
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/starboard/cryptography/software_aes.cc b/src/starboard/shared/starboard/cryptography/software_aes.cc
index 32793d4..d492543 100644
--- a/src/starboard/shared/starboard/cryptography/software_aes.cc
+++ b/src/starboard/shared/starboard/cryptography/software_aes.cc
@@ -62,7 +62,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/shared/starboard/cryptography/software_aes.h"
 
@@ -1573,4 +1573,4 @@
 }  // namespace shared
 }  // namespace starboard
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/starboard/cryptography/software_aes.h b/src/starboard/shared/starboard/cryptography/software_aes.h
index e05391f..18d5da5 100644
--- a/src/starboard/shared/starboard/cryptography/software_aes.h
+++ b/src/starboard/shared/starboard/cryptography/software_aes.h
@@ -63,7 +63,7 @@
 #ifndef STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_SOFTWARE_AES_H_
 #define STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_SOFTWARE_AES_H_
 
-#if SB_API_VERSION >= SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION >= 12
 #error "Starboard Crypto API is deprecated"
 #else
 
@@ -216,6 +216,6 @@
 }  // namespace shared
 }  // namespace starboard
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #endif  // STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_SOFTWARE_AES_H_
diff --git a/src/starboard/shared/starboard/drm/drm_get_metrics.cc b/src/starboard/shared/starboard/drm/drm_get_metrics.cc
new file mode 100644
index 0000000..457830b
--- /dev/null
+++ b/src/starboard/shared/starboard/drm/drm_get_metrics.cc
@@ -0,0 +1,38 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/drm.h"
+
+#include "starboard/common/log.h"
+#include "starboard/shared/starboard/drm/drm_system_internal.h"
+
+#if SB_API_VERSION >= 12
+
+const void* SbDrmGetMetrics(SbDrmSystem drm_system, int* size) {
+  if (size == NULL) {
+    SB_DLOG(WARNING) << "|size| cannot be NULL.";
+    return NULL;
+  }
+
+  *size = 0;
+
+  if (!SbDrmSystemIsValid(drm_system)) {
+    SB_DLOG(WARNING) << "Invalid drm system";
+    return NULL;
+  }
+
+  return drm_system->GetMetrics(size);
+}
+
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/shared/starboard/drm/drm_system_internal.h b/src/starboard/shared/starboard/drm/drm_system_internal.h
index 792159a..786a3b5 100644
--- a/src/starboard/shared/starboard/drm/drm_system_internal.h
+++ b/src/starboard/shared/starboard/drm/drm_system_internal.h
@@ -46,6 +46,8 @@
   virtual void UpdateServerCertificate(int ticket,
                                        const void* certificate,
                                        int certificate_size) = 0;
+
+  virtual const void* GetMetrics(int* size) = 0;
 };
 
 #endif  // STARBOARD_SHARED_STARBOARD_DRM_DRM_SYSTEM_INTERNAL_H_
diff --git a/src/starboard/shared/starboard/file_atomic_replace_write_file.cc b/src/starboard/shared/starboard/file_atomic_replace_write_file.cc
index 8d2dea9..deacb7a 100644
--- a/src/starboard/shared/starboard/file_atomic_replace_write_file.cc
+++ b/src/starboard/shared/starboard/file_atomic_replace_write_file.cc
@@ -19,7 +19,7 @@
 #include "starboard/common/log.h"
 #include "starboard/file.h"
 
-#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#if SB_API_VERSION >= 12
 
 namespace starboard {
 namespace shared {
@@ -68,4 +68,4 @@
 }  // namespace shared
 }  // namespace starboard
 
-#endif  // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/shared/starboard/file_atomic_replace_write_file.h b/src/starboard/shared/starboard/file_atomic_replace_write_file.h
index d89c750..f4657e6 100644
--- a/src/starboard/shared/starboard/file_atomic_replace_write_file.h
+++ b/src/starboard/shared/starboard/file_atomic_replace_write_file.h
@@ -18,7 +18,7 @@
 #include "starboard/configuration.h"
 #include "starboard/types.h"
 
-#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#if SB_API_VERSION >= 12
 
 namespace starboard {
 namespace shared {
@@ -32,6 +32,6 @@
 }  // namespace shared
 }  // namespace starboard
 
-#endif  // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #endif  // STARBOARD_SHARED_STARBOARD_FILE_ATOMIC_REPLACE_WRITE_FILE_H_
diff --git a/src/starboard/shared/starboard/lazy_initialization_internal.h b/src/starboard/shared/starboard/lazy_initialization_internal.h
index 58d3b84..e094919 100644
--- a/src/starboard/shared/starboard/lazy_initialization_internal.h
+++ b/src/starboard/shared/starboard/lazy_initialization_internal.h
@@ -23,7 +23,7 @@
 
 // INITIALIZED_STATE_UNINITIALIZED is defined in the header.
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
 #define INITIALIZED_STATE_INITIALIZING 1
 #define INITIALIZED_STATE_INITIALIZED 2
 #else
diff --git a/src/starboard/shared/starboard/lazy_initialization_public.h b/src/starboard/shared/starboard/lazy_initialization_public.h
index 6d4cd58..ff05bb4 100644
--- a/src/starboard/shared/starboard/lazy_initialization_public.h
+++ b/src/starboard/shared/starboard/lazy_initialization_public.h
@@ -28,7 +28,7 @@
 // "starboard/atomic.h".
 typedef int32_t InitializedState;
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
 #define INITIALIZED_STATE_UNINITIALIZED 0
 #else
 #define INITIALIZED_STATE_UNINITIALIZED 1
diff --git a/src/starboard/shared/starboard/link_receiver.cc b/src/starboard/shared/starboard/link_receiver.cc
index d92ff2c..bb97f5d 100644
--- a/src/starboard/shared/starboard/link_receiver.cc
+++ b/src/starboard/shared/starboard/link_receiver.cc
@@ -424,8 +424,8 @@
 }
 
 // static
-void LinkReceiver::Impl::HandleAccept(SbSocketWaiter /*waiter*/,
-                                      SbSocket /*socket*/,
+void LinkReceiver::Impl::HandleAccept(SbSocketWaiter waiter,
+                                      SbSocket socket,
                                       void* context,
                                       int ready_interests) {
   SB_DCHECK(context);
@@ -433,10 +433,10 @@
 }
 
 // static
-void LinkReceiver::Impl::HandleRead(SbSocketWaiter /*waiter*/,
+void LinkReceiver::Impl::HandleRead(SbSocketWaiter waiter,
                                     SbSocket socket,
                                     void* context,
-                                    int /*ready_interests*/) {
+                                    int ready_interests) {
   SB_DCHECK(context);
   reinterpret_cast<LinkReceiver::Impl*>(context)->OnReadReady(socket);
 }
diff --git a/src/starboard/shared/starboard/media/codec_util.cc b/src/starboard/shared/starboard/media/codec_util.cc
index 54c905f..982f519 100644
--- a/src/starboard/shared/starboard/media/codec_util.cc
+++ b/src/starboard/shared/starboard/media/codec_util.cc
@@ -626,8 +626,7 @@
   if (SbStringCompare(codec, "mp4a.40.", 8) == 0) {
     return kSbMediaAudioCodecAac;
   }
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    defined(SB_HAS_AC3_AUDIO)
+#if SB_API_VERSION >= 12 || defined(SB_HAS_AC3_AUDIO)
   if (kSbHasAc3Audio) {
     if (SbStringCompareAll(codec, "ac-3") == 0) {
       return kSbMediaAudioCodecAc3;
@@ -636,7 +635,7 @@
       return kSbMediaAudioCodecEac3;
     }
   }
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // defined(SB_HAS_AC3_AUDIO)
   if (SbStringCompare(codec, "opus", 4) == 0) {
     return kSbMediaAudioCodecOpus;
diff --git a/src/starboard/shared/starboard/media/codec_util_test.cc b/src/starboard/shared/starboard/media/codec_util_test.cc
index df2ede3..f6a11e2 100644
--- a/src/starboard/shared/starboard/media/codec_util_test.cc
+++ b/src/starboard/shared/starboard/media/codec_util_test.cc
@@ -25,7 +25,7 @@
 namespace media {
 namespace {
 
-const auto kIdrStartCode = 0x65;
+const uint8_t kIdrStartCode = 0x65;
 const auto kSpsStartCode = AvcParameterSets::kSpsStartCode;
 const auto kPpsStartCode = AvcParameterSets::kPpsStartCode;
 const auto kAnnexB = AvcParameterSets::kAnnexB;
diff --git a/src/starboard/shared/starboard/media/media.gyp b/src/starboard/shared/starboard/media/media.gyp
index 50e97b5..31bc43b 100644
--- a/src/starboard/shared/starboard/media/media.gyp
+++ b/src/starboard/shared/starboard/media/media.gyp
@@ -25,6 +25,10 @@
         '<(DEPTH)/starboard/shared/starboard/media/codec_util.h',
         '<(DEPTH)/starboard/shared/starboard/media/media_util.cc',
         '<(DEPTH)/starboard/shared/starboard/media/media_util.h',
+        '<(DEPTH)/starboard/shared/starboard/media/video_capabilities.cc',
+        '<(DEPTH)/starboard/shared/starboard/media/video_capabilities.h',
+        '<(DEPTH)/starboard/shared/starboard/media/vp9_util.cc',
+        '<(DEPTH)/starboard/shared/starboard/media/vp9_util.h',
       ],
       'dependencies': [
         '<(DEPTH)/starboard/starboard_headers_only.gyp:starboard_headers_only',
diff --git a/src/starboard/shared/starboard/media/media_get_buffer_alignment.cc b/src/starboard/shared/starboard/media/media_get_buffer_alignment.cc
index 9b0b88a..282c482 100644
--- a/src/starboard/shared/starboard/media/media_get_buffer_alignment.cc
+++ b/src/starboard/shared/starboard/media/media_get_buffer_alignment.cc
@@ -15,6 +15,5 @@
 #include "starboard/media.h"
 
 int SbMediaGetBufferAlignment(SbMediaType type) {
-  SB_UNREFERENCED_PARAMETER(type);
   return 1;
 }
diff --git a/src/starboard/shared/starboard/media/media_get_buffer_padding.cc b/src/starboard/shared/starboard/media/media_get_buffer_padding.cc
index 3384e9f..6c4ead1 100644
--- a/src/starboard/shared/starboard/media/media_get_buffer_padding.cc
+++ b/src/starboard/shared/starboard/media/media_get_buffer_padding.cc
@@ -15,6 +15,5 @@
 #include "starboard/media.h"
 
 int SbMediaGetBufferPadding(SbMediaType type) {
-  SB_UNREFERENCED_PARAMETER(type);
   return 0;
 }
diff --git a/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc b/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc
index f501f92..75bb435 100644
--- a/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc
+++ b/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc
@@ -18,7 +18,6 @@
                                 int resolution_width,
                                 int resolution_height,
                                 int bits_per_pixel) {
-  SB_UNREFERENCED_PARAMETER(codec);
   if ((resolution_width <= 1920 && resolution_height <= 1080) ||
       resolution_width == kSbMediaVideoResolutionDimensionInvalid ||
       resolution_height == kSbMediaVideoResolutionDimensionInvalid) {
diff --git a/src/starboard/shared/starboard/media/media_get_progressive_buffer_budget.cc b/src/starboard/shared/starboard/media/media_get_progressive_buffer_budget.cc
index 2c80ec7..54faf3e 100644
--- a/src/starboard/shared/starboard/media/media_get_progressive_buffer_budget.cc
+++ b/src/starboard/shared/starboard/media/media_get_progressive_buffer_budget.cc
@@ -18,9 +18,5 @@
                                       int resolution_width,
                                       int resolution_height,
                                       int bits_per_pixel) {
-  SB_UNREFERENCED_PARAMETER(codec);
-  SB_UNREFERENCED_PARAMETER(resolution_width);
-  SB_UNREFERENCED_PARAMETER(resolution_height);
-  SB_UNREFERENCED_PARAMETER(bits_per_pixel);
   return 12 * 1024 * 1024;
 }
diff --git a/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc b/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc
index 339f204..82313dd 100644
--- a/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc
+++ b/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc
@@ -18,7 +18,6 @@
                                 int resolution_width,
                                 int resolution_height,
                                 int bits_per_pixel) {
-  SB_UNREFERENCED_PARAMETER(codec);
   if ((resolution_width <= 1920 && resolution_height <= 1080) ||
       resolution_width == kSbMediaVideoResolutionDimensionInvalid ||
       resolution_height == kSbMediaVideoResolutionDimensionInvalid) {
diff --git a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc
index ff2a9d3..c65f647 100644
--- a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc
+++ b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc
@@ -19,14 +19,10 @@
 #include "starboard/media.h"
 
 bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
                              const char* content_type,
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
                              int64_t bitrate) {
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
-  SB_UNREFERENCED_PARAMETER(content_type);
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
-
   if (audio_codec == kSbMediaAudioCodecAac) {
     return bitrate <= kSbMediaMaxAudioBitrateInBitsPerSecond;
   }
diff --git a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc
index 7bdcec8..afcccd4 100644
--- a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc
+++ b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc
@@ -19,14 +19,10 @@
 #include "starboard/media.h"
 
 bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
                              const char* content_type,
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
                              int64_t bitrate) {
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
-  SB_UNREFERENCED_PARAMETER(content_type);
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
-
   return audio_codec == kSbMediaAudioCodecAac &&
          bitrate <= kSbMediaMaxAudioBitrateInBitsPerSecond;
 }
diff --git a/src/starboard/shared/starboard/media/media_support_internal.h b/src/starboard/shared/starboard/media/media_support_internal.h
index b106f0a..02bc6ae 100644
--- a/src/starboard/shared/starboard/media/media_support_internal.h
+++ b/src/starboard/shared/starboard/media/media_support_internal.h
@@ -58,7 +58,7 @@
 //        it indicates that the fps shouldn't be considered.
 // |decode_to_texture_required|: Whether or not the resulting video frames can
 //                               be decoded and used as textures by the GPU.
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
                              const char* content_type,
@@ -74,7 +74,7 @@
                              int fps,
                              bool decode_to_texture_required);
 
-#else  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#else  // SB_API_VERSION >= 12
 
 bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
 #if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
@@ -91,7 +91,7 @@
                              int fps,
                              bool decode_to_texture_required);
 
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
 
 // Indicates whether this platform supports |audio_codec| at |bitrate|.
 // If |audio_codec| is not supported under any condition, this function
@@ -102,17 +102,17 @@
 //                 interface if there is any.  Otherwise it will be set to "".
 //                 It should never to set to NULL.
 // |bitrate|: The media's bitrate.
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
                              const char* content_type,
                              int64_t bitrate);
 
-#else  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#else  // SB_API_VERSION >= 12
 
 bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, int64_t bitrate);
 
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #if !SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
 // Indicates whether this platform supports |transfer_id| as a transfer
diff --git a/src/starboard/shared/starboard/media/media_tests.gypi b/src/starboard/shared/starboard/media/media_tests.gypi
index a07a89b..d581f6f 100644
--- a/src/starboard/shared/starboard/media/media_tests.gypi
+++ b/src/starboard/shared/starboard/media/media_tests.gypi
@@ -20,6 +20,8 @@
       '<(DEPTH)/starboard/shared/starboard/media/avc_util_test.cc',
       '<(DEPTH)/starboard/shared/starboard/media/codec_util_test.cc',
       '<(DEPTH)/starboard/shared/starboard/media/mime_type_test.cc',
+      '<(DEPTH)/starboard/shared/starboard/media/video_capabilities_test.cc',
+      '<(DEPTH)/starboard/shared/starboard/media/vp9_util_test.cc',
     ],
   },
 }
diff --git a/src/starboard/shared/starboard/media/media_util.cc b/src/starboard/shared/starboard/media/media_util.cc
index d309add..9b721cb 100644
--- a/src/starboard/shared/starboard/media/media_util.cc
+++ b/src/starboard/shared/starboard/media/media_util.cc
@@ -61,9 +61,9 @@
   int bitrate = mime_type.GetParamIntValue("bitrate", kDefaultBitRate);
 
   if (!SbMediaIsAudioSupported(audio_codec,
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
                                mime_type.raw_content_type().c_str(),
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
                                bitrate)) {
     return false;
   }
@@ -74,7 +74,7 @@
       return false;
     case kSbMediaAudioCodecAac:
       return mime_type.subtype() == "mp4";
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || SB_HAS(AC3_AUDIO)
+#if SB_API_VERSION >= 12 || SB_HAS(AC3_AUDIO)
     case kSbMediaAudioCodecAc3:
       if (!kSbHasAc3Audio) {
         SB_NOTREACHED() << "AC3 audio is not enabled on this platform. To "
@@ -89,7 +89,7 @@
         return false;
       }
       return mime_type.subtype() == "mp4";
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(AC3_AUDIO)
     case kSbMediaAudioCodecOpus:
     case kSbMediaAudioCodecVorbis:
@@ -162,9 +162,9 @@
 
 #if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
   if (!SbMediaIsVideoSupported(video_codec,
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
                                mime_type.raw_content_type().c_str(),
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
                                profile, level, bit_depth, primary_id,
                                transfer_id, matrix_id, width, height, bitrate,
                                fps, decode_to_texture_required)) {
@@ -424,7 +424,7 @@
       return "none";
     case kSbMediaAudioCodecAac:
       return "aac";
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || SB_HAS(AC3_AUDIO)
+#if SB_API_VERSION >= 12 || SB_HAS(AC3_AUDIO)
     case kSbMediaAudioCodecAc3:
       if (!kSbHasAc3Audio) {
         SB_NOTREACHED() << "AC3 audio is not enabled on this platform. To "
@@ -439,7 +439,7 @@
         return "invalid";
       }
       return "ec3";
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(AC3_AUDIO)
     case kSbMediaAudioCodecOpus:
       return "opus";
diff --git a/src/starboard/shared/starboard/media/mime_type.cc b/src/starboard/shared/starboard/media/mime_type.cc
index f84439a..eae8eae 100644
--- a/src/starboard/shared/starboard/media/mime_type.cc
+++ b/src/starboard/shared/starboard/media/mime_type.cc
@@ -14,6 +14,9 @@
 
 #include "starboard/shared/starboard/media/mime_type.h"
 
+#include <locale>
+#include <sstream>
+
 #include "starboard/character.h"
 #include "starboard/common/log.h"
 #include "starboard/common/string.h"
@@ -35,8 +38,10 @@
     return MimeType::kParamTypeInteger;
   }
   float f;
-  if (SbStringScanF(value.c_str(), "%g%n", &f, &count) == 1 &&
-      count == value.size()) {
+  std::stringstream buffer(value);
+  buffer.imbue(std::locale::classic());
+  buffer >> f;
+  if (!buffer.fail() && buffer.rdbuf()->in_avail() == 0) {
     return MimeType::kParamTypeFloat;
   }
   return MimeType::kParamTypeString;
@@ -197,7 +202,9 @@
   }
 
   float f;
-  SbStringScanF(params_[index].value.c_str(), "%g", &f);
+  std::stringstream buffer(params_[index].value.c_str());
+  buffer.imbue(std::locale::classic());
+  buffer >> f;
 
   return f;
 }
diff --git a/src/starboard/shared/starboard/media/video_capabilities.cc b/src/starboard/shared/starboard/media/video_capabilities.cc
new file mode 100644
index 0000000..78d8fd8
--- /dev/null
+++ b/src/starboard/shared/starboard/media/video_capabilities.cc
@@ -0,0 +1,115 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/starboard/media/video_capabilities.h"
+
+#include "starboard/common/log.h"
+#include "starboard/format_string.h"
+#include "starboard/shared/starboard/media/media_util.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+
+VideoCapabilities::Rule::Rule(SbMediaVideoCodec codec,
+                              int width,
+                              int height,
+                              int fps)
+    : codec_(codec), width_(width), height_(height), fps_(fps) {
+  SB_DCHECK(width >= 0);
+  SB_DCHECK(height >= 0);
+  SB_DCHECK(fps >= 0);
+  SB_DCHECK(codec_ != kSbMediaVideoCodecNone);
+}
+
+std::string VideoCapabilities::Rule::AsString() const {
+  return FormatString("(%s, %d x %d @ %d fps)", GetCodecName(codec_), width_,
+                      height_, fps_);
+}
+
+bool VideoCapabilities::Rule::CanBeInferredBy(const Rule& that) const {
+  return codec_ == that.codec_ && width_ <= that.width_ &&
+         height_ <= that.height_ && fps_ <= that.fps_;
+}
+
+void VideoCapabilities::AddSdrRule(SbMediaVideoCodec codec,
+                                   int width,
+                                   int height,
+                                   int fps) {
+  SB_DCHECK(width > 0);
+  SB_DCHECK(height > 0);
+  SB_DCHECK(fps > 0);
+  AddRule(Rule(codec, width, height, fps), &sdr_rules_);
+}
+
+void VideoCapabilities::AddHdrRule(SbMediaVideoCodec codec,
+                                   int width,
+                                   int height,
+                                   int fps) {
+  SB_DCHECK(width > 0);
+  SB_DCHECK(height > 0);
+  SB_DCHECK(fps > 0);
+  AddRule(Rule(codec, width, height, fps), &hdr_rules_);
+}
+
+bool VideoCapabilities::IsSupported(SbMediaVideoCodec codec,
+                                    SbMediaTransferId transfer_id,
+                                    int width,
+                                    int height,
+                                    int fps) const {
+  Rule rule(codec, width, height, fps);
+  if (IsSDRVideo(8, kSbMediaPrimaryIdBt709, transfer_id,
+                 kSbMediaMatrixIdBt709)) {
+    return IsSupported(rule, sdr_rules_);
+  }
+  return IsSupported(rule, hdr_rules_);
+}
+
+// static
+void VideoCapabilities::AddRule(const Rule& new_rule, Rules* rules) {
+  SB_DCHECK(rules);
+
+#if !defined(COBALT_BUILD_TYPE_GOLD)
+  for (auto& rule : *rules) {
+    if (rule.CanBeInferredBy(new_rule)) {
+      SB_LOG(WARNING) << "Existing rule " << rule.AsString()
+                      << " can be inferred by new rule " << new_rule.AsString();
+    } else if (new_rule.CanBeInferredBy(rule)) {
+      SB_LOG(WARNING) << "New rule " << new_rule.AsString()
+                      << " can be inferred by existing rule "
+                      << rule.AsString();
+    }
+  }
+#endif  // defined(COBALT_BUILD_TYPE_GOLD)
+
+  rules->push_back(new_rule);
+}
+
+// static
+bool VideoCapabilities::IsSupported(const Rule& rule_to_check,
+                                    const Rules& rules) {
+  for (auto& rule : rules) {
+    if (rule_to_check.CanBeInferredBy(rule)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+}  // namespace media
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/shared/starboard/media/video_capabilities.h b/src/starboard/shared/starboard/media/video_capabilities.h
new file mode 100644
index 0000000..28d5b04
--- /dev/null
+++ b/src/starboard/shared/starboard/media/video_capabilities.h
@@ -0,0 +1,79 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_STARBOARD_MEDIA_VIDEO_CAPABILITIES_H_
+#define STARBOARD_SHARED_STARBOARD_MEDIA_VIDEO_CAPABILITIES_H_
+
+#include <string>
+#include <vector>
+
+#include "starboard/media.h"
+#include "starboard/shared/internal_only.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+
+// Allows to query video capabilities via simple, preset rules.  With a setup
+// like:
+//   VideoCapabilities video_capabilities;
+//
+//   video_capabilities.AddSdrRule(kSbMediaVideoCodecH264, 1920, 1080, 60);
+//   video_capabilities.AddSdrRule(kSbMediaVideoCodecVp9, 3840, 2160, 30);
+//   video_capabilities.AddSdrRule(kSbMediaVideoCodecVp9, 2560, 1440, 60);
+// We can query whether certain playbacks are supported using:
+//   video_capabilities.IsSupported(
+//      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 640, 480, 30);
+class VideoCapabilities {
+ public:
+  void AddSdrRule(SbMediaVideoCodec codec, int width, int height, int fps);
+  void AddHdrRule(SbMediaVideoCodec codec, int width, int height, int fps);
+
+  bool IsSupported(SbMediaVideoCodec codec,
+                   SbMediaTransferId transfer_id,
+                   int width,
+                   int height,
+                   int fps) const;
+
+ private:
+  class Rule {
+   public:
+    Rule(SbMediaVideoCodec codec, int width, int height, int fps);
+
+    std::string AsString() const;
+    bool CanBeInferredBy(const Rule& that) const;
+
+   private:
+    const SbMediaVideoCodec codec_;
+    const int width_;
+    const int height_;
+    const int fps_;
+  };
+
+  typedef std::vector<Rule> Rules;
+
+  static void AddRule(const Rule& new_rule, Rules* rules);
+  static bool IsSupported(const Rule& rule_to_check, const Rules& rules);
+
+  Rules sdr_rules_;
+  Rules hdr_rules_;
+};
+
+}  // namespace media
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_SHARED_STARBOARD_MEDIA_VIDEO_CAPABILITIES_H_
diff --git a/src/starboard/shared/starboard/media/video_capabilities_test.cc b/src/starboard/shared/starboard/media/video_capabilities_test.cc
new file mode 100644
index 0000000..4f50100
--- /dev/null
+++ b/src/starboard/shared/starboard/media/video_capabilities_test.cc
@@ -0,0 +1,230 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/starboard/media/video_capabilities.h"
+
+#include "starboard/media.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+namespace {
+
+TEST(VideoCapabilitiesTest, EmptyObject) {
+  VideoCapabilities video_capabilities;
+
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 640, 480, 30));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdBt709, 640, 480, 30));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferId10BitBt2020, 640, 480, 30));
+}
+
+TEST(VideoCapabilitiesTest, H264SdrWithOneRule) {
+  VideoCapabilities video_capabilities;
+
+  video_capabilities.AddSdrRule(kSbMediaVideoCodecH264, 1920, 1080, 60);
+
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 640, 480, 30));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 1080, 30));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 1080, 60));
+
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 640, 480, 61));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 3840, 1080, 30));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1921, 1080, 30));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 1081, 30));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 1080, 61));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 2160, 30));
+
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferId10BitBt2020, 640, 480, 30));
+
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdBt709, 640, 480, 30));
+}
+
+TEST(VideoCapabilitiesTest, H264SdrWithMixedRules) {
+  VideoCapabilities video_capabilities;
+
+  video_capabilities.AddSdrRule(kSbMediaVideoCodecH264, 1920, 1080, 30);
+  video_capabilities.AddSdrRule(kSbMediaVideoCodecH264, 1280, 720, 60);
+
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 640, 480, 30));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 640, 480, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1280, 720, 30));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1280, 720, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 1080, 30));
+
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 1080, 60));
+}
+
+TEST(VideoCapabilitiesTest, H264SdrWithRedundantRules) {
+  VideoCapabilities video_capabilities;
+
+  video_capabilities.AddSdrRule(kSbMediaVideoCodecH264, 1920, 1080, 60);
+  video_capabilities.AddSdrRule(kSbMediaVideoCodecH264, 1920, 1080, 30);
+
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 640, 480, 30));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 1080, 30));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 1080, 60));
+
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 640, 480, 61));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 3840, 1080, 30));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 2160, 30));
+
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferId10BitBt2020, 640, 480, 30));
+
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdBt709, 640, 480, 30));
+}
+
+TEST(VideoCapabilitiesTest, IsSupportedWithZeroValues) {
+  VideoCapabilities video_capabilities;
+
+  video_capabilities.AddSdrRule(kSbMediaVideoCodecH264, 1920, 1080, 60);
+  video_capabilities.AddHdrRule(kSbMediaVideoCodecH264, 1920, 1080, 60);
+  video_capabilities.AddSdrRule(kSbMediaVideoCodecVp9, 1920, 1080, 60);
+  video_capabilities.AddHdrRule(kSbMediaVideoCodecVp9, 1920, 1080, 60);
+
+  EXPECT_TRUE(video_capabilities.IsSupported(kSbMediaVideoCodecH264,
+                                             kSbMediaTransferIdBt709, 0, 0, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 0, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 1080, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 1080, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 0, 1080, 0));
+
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferId10BitBt2020, 0, 0, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferId10BitBt2020, 1920, 0, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferId10BitBt2020, 1920, 1080, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferId10BitBt2020, 1920, 1080, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferId10BitBt2020, 0, 1080, 0));
+
+  EXPECT_TRUE(video_capabilities.IsSupported(kSbMediaVideoCodecVp9,
+                                             kSbMediaTransferIdBt709, 0, 0, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdBt709, 1920, 0, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdBt709, 1920, 1080, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdBt709, 1920, 1080, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdBt709, 0, 1080, 0));
+
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferId10BitBt2020, 0, 0, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferId10BitBt2020, 1920, 0, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferId10BitBt2020, 1920, 1080, 0));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferId10BitBt2020, 1920, 1080, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferId10BitBt2020, 0, 1080, 0));
+
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 0, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 0, 1080, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferId10BitBt2020, 1920, 0, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferId10BitBt2020, 0, 1080, 60));
+
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdBt709, 1920, 0, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdBt709, 0, 1080, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferId10BitBt2020, 1920, 0, 60));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferId10BitBt2020, 0, 1080, 60));
+}
+
+TEST(VideoCapabilitiesTest, MultiCodecsAndDynamicRanges) {
+  VideoCapabilities video_capabilities;
+
+  video_capabilities.AddSdrRule(kSbMediaVideoCodecH264, 1920, 1080, 60);
+
+  video_capabilities.AddSdrRule(kSbMediaVideoCodecVp9, 3840, 2160, 30);
+  video_capabilities.AddSdrRule(kSbMediaVideoCodecVp9, 2560, 1440, 60);
+
+  video_capabilities.AddHdrRule(kSbMediaVideoCodecVp9, 2560, 1440, 30);
+  video_capabilities.AddHdrRule(kSbMediaVideoCodecVp9, 1920, 1080, 60);
+
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 640, 480, 30));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferId10BitBt2020, 640, 480, 30));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 1920, 1080, 120));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecH264, kSbMediaTransferIdBt709, 2560, 1440, 15));
+
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdBt709, 3840, 2160, 30));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdBt709, 7680, 4320, 15));
+
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferId10BitBt2020, 640, 480, 30));
+  EXPECT_TRUE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferIdAribStdB67, 1920, 1080, 60));
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecVp9, kSbMediaTransferId10BitBt2020, 2560, 1440, 60));
+
+#if SB_API_VERSION >= 11
+  EXPECT_FALSE(video_capabilities.IsSupported(
+      kSbMediaVideoCodecAv1, kSbMediaTransferId10BitBt2020, 2560, 1440, 30));
+#endif  // SB_API_VERSION >= 11
+}
+
+}  // namespace
+}  // namespace media
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/shared/starboard/media/vp9_util.cc b/src/starboard/shared/starboard/media/vp9_util.cc
new file mode 100644
index 0000000..9f04181
--- /dev/null
+++ b/src/starboard/shared/starboard/media/vp9_util.cc
@@ -0,0 +1,119 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/starboard/media/vp9_util.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+
+namespace {
+
+// Reading size as u_bytes(n):
+//   u_bytes(n) {
+//     value = 0
+//     for (i = 0; i < n; ++i)
+//       value |= byte << (i * 8) u(8)
+//     return value
+//   }
+size_t ReadSize(const uint8_t* data, size_t bytes_of_size) {
+  size_t size = 0;
+  for (size_t i = 0; i < bytes_of_size; ++i) {
+    size |= static_cast<size_t>(data[i]) << (i * 8);
+  }
+  return size;
+}
+
+}  // namespace
+
+Vp9FrameParser::Vp9FrameParser(const void* vp9_frame, size_t size) {
+  const uint8_t* frame_in_uint8 = static_cast<const uint8_t*>(vp9_frame);
+
+  // To determine whether a chunk of data has a superframe index, check the last
+  // byte in the chunk for the marker 3 bits (0b110xxxxx).
+  uint8_t last_byte = size == 0 ? 0 : frame_in_uint8[size - 1];
+  if ((last_byte >> 5) == 0b110 && ParseSuperFrame(frame_in_uint8, size)) {
+    return;
+  }
+  // Not a superframe, or ParseSuperFrame() fails, treat the whole input as a
+  // single subframe.
+  subframes_[0].address = frame_in_uint8;
+  subframes_[0].size = size;
+  number_of_subframes_ = 1;
+}
+
+bool Vp9FrameParser::ParseSuperFrame(const uint8_t* frame,
+                                     size_t size_of_superframe) {
+  uint8_t last_byte = frame[size_of_superframe - 1];
+  // mask 2 bits (0bxxx11xxx) and add 1 to get the size in bytes for each frame
+  // size.
+  size_t bytes_of_size = ((last_byte & 0b00011000) >> 3) + 1;
+  // mask 3 bits (0bxxxxx111) and add 1 to get the # of frame sizes encoded in
+  // the index.
+  number_of_subframes_ = (last_byte & 0b00000111) + 1;
+  // Calculate the total size of the index as follows:
+  // 2 + number of frame sizes encoded * number of bytes to hold each frame
+  // size.
+  size_t total_bytes_of_superframe_index =
+      2 + number_of_subframes_ * bytes_of_size;
+
+  SB_DCHECK(number_of_subframes_ <= kMaxNumberOfSubFrames);
+
+  if (total_bytes_of_superframe_index > size_of_superframe) {
+    SB_LOG(WARNING) << "Size of vp9 superframe index is less than the frame"
+                    << " size.";
+    return false;
+  }
+
+  // Go to the first byte of the superframe index, and check that it matches the
+  // last byte of the superframe index.
+  const uint8_t* first_byte =
+      frame + (size_of_superframe - total_bytes_of_superframe_index);
+  if (*first_byte != last_byte) {
+    SB_LOG(WARNING) << "Vp9 superframe marker bytes doesn't match.";
+    return false;
+  }
+
+  size_t accumulated_size_of_subframes = 0;
+  // Skip the first byte, which is a marker.
+  const uint8_t* address_of_sizes = first_byte + 1;
+  for (size_t i = 0; i < number_of_subframes_; ++i) {
+    subframes_[i].size = ReadSize(address_of_sizes, bytes_of_size);
+    subframes_[i].address = frame + accumulated_size_of_subframes;
+    address_of_sizes += bytes_of_size;
+    accumulated_size_of_subframes += subframes_[i].size;
+  }
+
+  if (accumulated_size_of_subframes + total_bytes_of_superframe_index >
+      size_of_superframe) {
+    SB_LOG(WARNING) << "Accumulated size of vp9 subframes is too big.";
+    return false;
+  }
+
+  if (accumulated_size_of_subframes + total_bytes_of_superframe_index !=
+      size_of_superframe) {
+    // There are some empty space before the superframe index, that's probably
+    // still valid but let's issue a warning.
+    SB_LOG(WARNING) << "Accumulated size of vp9 subframes doesn't match.";
+  }
+
+  // Now we can finally confirm that it is a valid superframe.
+  return true;
+}
+
+}  // namespace media
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/shared/starboard/media/vp9_util.h b/src/starboard/shared/starboard/media/vp9_util.h
new file mode 100644
index 0000000..eb28a1a
--- /dev/null
+++ b/src/starboard/shared/starboard/media/vp9_util.h
@@ -0,0 +1,69 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_STARBOARD_MEDIA_VP9_UTIL_H_
+#define STARBOARD_SHARED_STARBOARD_MEDIA_VP9_UTIL_H_
+
+#include "starboard/common/log.h"
+#include "starboard/types.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+
+// This class parses a vp9 frame, and allows to access the contained frames
+// (which will be called subframes) of a superframe.
+// When the input isn't a superframe, the class will return the whole input as
+// one subframe.
+// Please refer to "section 3, Superframe" at
+// http://downloads.webmproject.org/docs/vp9/vp9-bitstream_superframe-and-uncompressed-header_v1.0.pdf
+// for the superframe syntax.
+class Vp9FrameParser {
+ public:
+  static constexpr size_t kMaxNumberOfSubFrames = 8;
+
+  Vp9FrameParser(const void* vp9_frame, size_t size);
+
+  size_t number_of_subframes() const {
+    SB_DCHECK(number_of_subframes_ > 0);
+    return number_of_subframes_;
+  }
+  const uint8_t* address_of_subframe(size_t index) const {
+    SB_DCHECK(index < number_of_subframes_);
+    return subframes_[index].address;
+  }
+  size_t size_of_subframe(size_t index) const {
+    SB_DCHECK(index < number_of_subframes_);
+    return subframes_[index].size;
+  }
+
+ private:
+  struct Subframe {
+    const uint8_t* address = nullptr;
+    size_t size = 0;
+  };
+
+  bool ParseSuperFrame(const uint8_t* frame, size_t size);
+
+  Subframe subframes_[kMaxNumberOfSubFrames];
+  size_t number_of_subframes_ = 0;
+};
+
+}  // namespace media
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_SHARED_STARBOARD_MEDIA_VP9_UTIL_H_
diff --git a/src/starboard/shared/starboard/media/vp9_util_test.cc b/src/starboard/shared/starboard/media/vp9_util_test.cc
new file mode 100644
index 0000000..ff91201
--- /dev/null
+++ b/src/starboard/shared/starboard/media/vp9_util_test.cc
@@ -0,0 +1,173 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/starboard/media/vp9_util.h"
+
+#include <vector>
+
+#include "starboard/common/log.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+namespace {
+
+std::vector<uint8_t> operator+(const std::vector<uint8_t>& left,
+                               const std::vector<uint8_t>& right) {
+  std::vector<uint8_t> result(left);
+  result.insert(result.end(), right.begin(), right.end());
+  return result;
+}
+
+uint8_t CreateSuperframeMarker(size_t bytes_of_size,
+                               size_t number_of_subframes) {
+  SB_DCHECK(bytes_of_size > 0);
+  SB_DCHECK(bytes_of_size <= 4);
+  SB_DCHECK(number_of_subframes > 0);
+  SB_DCHECK(number_of_subframes <= Vp9FrameParser::kMaxNumberOfSubFrames);
+
+  return static_cast<uint8_t>(0b11000000 | ((bytes_of_size - 1) << 3) |
+                              (number_of_subframes - 1));
+}
+
+std::vector<uint8_t> ConvertSizeToBytes(size_t size, size_t bytes_of_size) {
+  SB_DCHECK(bytes_of_size > 0);
+  SB_DCHECK(bytes_of_size <= 4);
+
+  std::vector<uint8_t> size_in_bytes;
+
+  while (bytes_of_size > 0) {
+    size_in_bytes.push_back(size % 256);
+    --bytes_of_size;
+    size /= 256;
+  }
+
+  SB_DCHECK(size == 0);
+
+  return size_in_bytes;
+}
+
+void AddSubframe(const std::vector<uint8_t>& subframe,
+                 std::vector<uint8_t>* frame_data,
+                 std::vector<uint8_t>* superframe_metadata,
+                 size_t bytes_of_size) {
+  SB_DCHECK(frame_data);
+  SB_DCHECK(superframe_metadata);
+
+  frame_data->insert(frame_data->end(), subframe.begin(), subframe.end());
+  auto size_in_bytes = ConvertSizeToBytes(subframe.size(), bytes_of_size);
+  superframe_metadata->insert(superframe_metadata->end(), size_in_bytes.begin(),
+                              size_in_bytes.end());
+}
+
+TEST(Vp9FrameParserTests, EmptyFrame) {
+  Vp9FrameParser parser(nullptr, 0);
+
+  ASSERT_EQ(parser.number_of_subframes(), 1);
+  EXPECT_EQ(parser.size_of_subframe(0), 0);
+}
+
+TEST(Vp9FrameParserTests, NonSuperFrame) {
+  std::vector<uint8_t> kFrameData({1, 2, 3, 0});
+  Vp9FrameParser parser(kFrameData.data(), kFrameData.size());
+
+  ASSERT_EQ(parser.number_of_subframes(), 1);
+  EXPECT_EQ(parser.address_of_subframe(0), kFrameData.data());
+  EXPECT_EQ(parser.size_of_subframe(0), kFrameData.size());
+}
+
+TEST(Vp9FrameParserTests, SuperFrames) {
+  std::vector<uint8_t> kFrameData({1, 2, 3, 4, 5, 6, 7, 8, 9, 0});
+
+  for (size_t bytes_of_size = 1; bytes_of_size <= 4; ++bytes_of_size) {
+    for (size_t number_of_subframes = 1;
+         number_of_subframes <= Vp9FrameParser::kMaxNumberOfSubFrames;
+         ++number_of_subframes) {
+      std::vector<uint8_t> frame_data;
+      std::vector<uint8_t> superframe_metadata;
+
+      const uint8_t superframe_marker =
+          CreateSuperframeMarker(bytes_of_size, number_of_subframes);
+
+      superframe_metadata.push_back(superframe_marker);
+
+      for (size_t subframe_index = 0; subframe_index < number_of_subframes;
+           ++subframe_index) {
+        AddSubframe(kFrameData, &frame_data, &superframe_metadata,
+                    bytes_of_size);
+      }
+
+      superframe_metadata.push_back(superframe_marker);
+
+      auto superframe = frame_data + superframe_metadata;
+
+      Vp9FrameParser parser(superframe.data(), superframe.size());
+
+      ASSERT_EQ(parser.number_of_subframes(), number_of_subframes);
+      for (size_t subframe_index = 0; subframe_index < number_of_subframes;
+           ++subframe_index) {
+        EXPECT_EQ(parser.address_of_subframe(subframe_index),
+                  superframe.data() + subframe_index * kFrameData.size());
+        EXPECT_EQ(parser.size_of_subframe(subframe_index), kFrameData.size());
+      }
+    }
+  }
+}
+
+TEST(Vp9FrameParserTests, SuperFramesWithEmptySubframes) {
+  std::vector<uint8_t> kEmptyFrameData;
+
+  for (size_t bytes_of_size = 1; bytes_of_size <= 4; ++bytes_of_size) {
+    for (size_t number_of_subframes = 1;
+         number_of_subframes <= Vp9FrameParser::kMaxNumberOfSubFrames;
+         ++number_of_subframes) {
+      std::vector<uint8_t> frame_data;
+      std::vector<uint8_t> superframe_metadata;
+
+      const uint8_t superframe_marker =
+          CreateSuperframeMarker(bytes_of_size, number_of_subframes);
+
+      superframe_metadata.push_back(superframe_marker);
+
+      for (size_t subframe_index = 0; subframe_index < number_of_subframes;
+           ++subframe_index) {
+        AddSubframe(kEmptyFrameData, &frame_data, &superframe_metadata,
+                    bytes_of_size);
+      }
+
+      superframe_metadata.push_back(superframe_marker);
+
+      auto superframe = frame_data + superframe_metadata;
+
+      Vp9FrameParser parser(superframe.data(), superframe.size());
+
+      ASSERT_EQ(parser.number_of_subframes(), number_of_subframes);
+      for (size_t subframe_index = 0; subframe_index < number_of_subframes;
+           ++subframe_index) {
+        EXPECT_EQ(parser.address_of_subframe(subframe_index),
+                  superframe.data() + subframe_index * kEmptyFrameData.size());
+        EXPECT_EQ(parser.size_of_subframe(subframe_index),
+                  kEmptyFrameData.size());
+      }
+    }
+  }
+}
+
+}  // namespace
+}  // namespace media
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/common/memory.cc b/src/starboard/shared/starboard/memory.cc
similarity index 100%
rename from src/starboard/common/memory.cc
rename to src/starboard/shared/starboard/memory.cc
diff --git a/src/starboard/shared/starboard/net_log.cc b/src/starboard/shared/starboard/net_log.cc
index f0a48dc..c63c27b 100644
--- a/src/starboard/shared/starboard/net_log.cc
+++ b/src/starboard/shared/starboard/net_log.cc
@@ -372,7 +372,7 @@
   }
 
  private:
-  void WriterTask(Semaphore* /*joined_sema*/) {
+  void WriterTask(Semaphore* joined_sema) {
     while (true) {
       writer_thread_sema_.Take();
 
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc
index 08f306e..7615d4d 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc
@@ -405,37 +405,22 @@
   }
 }
 
-void AudioRendererImpl::ConsumeFrames(int frames_consumed
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-                                      ,
-                                      SbTime frames_consumed_at
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-) {
+void AudioRendererImpl::ConsumeFrames(int frames_consumed,
+                                      SbTime frames_consumed_at) {
 #if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
   sink_callbacks_since_last_check_.increment();
 #endif  // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
 
-// Note that occasionally thread context switch may cause that the time
-// recorded here is several milliseconds later than the time |frames_consumed|
-// is recorded.  This causes the audio time to drift as much as the difference
-// between the two times.
-// This is usually not a huge issue as:
-// 1. It happens rarely.
-// 2. It doesn't accumulate.
-// 3. It doesn't affect frame presenting even with a 60fps video.
-// However, if this ever becomes a problem, we can smooth it out over multiple
-// ConsumeFrames() calls.
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  if (!kSbHasAsyncAudioFramesReporting) {
-    frames_consumed_at = SbTimeGetMonotonicNow();
-  }
-#elif SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION && \
-    !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-  SbTime frames_consumed_at = SbTimeGetMonotonicNow();
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION &&
-        // !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+  // Note that occasionally thread context switch may cause that the time
+  // recorded here is several milliseconds later than the time |frames_consumed|
+  // is recorded.  This causes the audio time to drift as much as the difference
+  // between the two times.
+  // This is usually not a huge issue as:
+  // 1. It happens rarely.
+  // 2. It doesn't accumulate.
+  // 3. It doesn't affect frame presenting even with a 60fps video.
+  // However, if this ever becomes a problem, we can smooth it out over multiple
+  // ConsumeFrames() calls.
 
   ScopedTryLock lock(mutex_);
   if (lock.is_locked()) {
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h b/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h
index e984ec2..93010f3 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h
@@ -136,14 +136,7 @@
                        int* offset_in_frames,
                        bool* is_playing,
                        bool* is_eos_reached) override;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
   void ConsumeFrames(int frames_consumed, SbTime frames_consumed_at) override;
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-  void ConsumeFrames(int frames_consumed) override;
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
   void OnError(bool capability_changed) override;
 
   void UpdateVariablesOnSinkThread_Locked(SbTime system_time_on_consume_frames);
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_sink.h b/src/starboard/shared/starboard/player/filter/audio_renderer_sink.h
index fad7279..2d98c3e 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_sink.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_sink.h
@@ -34,15 +34,8 @@
                                  int* offset_in_frames,
                                  bool* is_playing,
                                  bool* is_eos_reached) = 0;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
     virtual void ConsumeFrames(int frames_consumed,
                                SbTime frames_consumed_at) = 0;
-#else   //  SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        //  SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-    virtual void ConsumeFrames(int frames_consumed) = 0;
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 
     // When |capability_changed| is true, it hints that the error is caused by a
     // a transisent capability on the platform.  The app should retry playback
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc
index a9fa194..270f8a5 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc
@@ -85,9 +85,9 @@
         audio_frame_storage_type, frame_buffers, frames_per_channel,
         &AudioRendererSinkImpl::UpdateSourceStatusFunc,
         &AudioRendererSinkImpl::ConsumeFramesFunc,
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#if SB_API_VERSION >= 12
         &AudioRendererSinkImpl::ErrorFunc,
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#endif  // SB_API_VERSION >= 12
         this);
     if (!audio_sink_type->IsValid(audio_sink_)) {
       SB_LOG(WARNING) << "Created invalid SbAudioSink from "
@@ -102,9 +102,9 @@
             audio_frame_storage_type, frame_buffers, frames_per_channel,
             &AudioRendererSinkImpl::UpdateSourceStatusFunc,
             &AudioRendererSinkImpl::ConsumeFramesFunc,
-#if SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#if SB_API_VERSION >= 12
             &AudioRendererSinkImpl::ErrorFunc,
-#endif  // SB_API_VERSION >= SB_AUDIO_SINK_ERROR_HANDLING_VERSION
+#endif  // SB_API_VERSION >= 12
             this);
         if (!fallback_type->IsValid(audio_sink_)) {
           SB_LOG(ERROR) << "Failed to create SbAudioSink from Fallback type.";
@@ -176,34 +176,16 @@
 }
 
 // static
-void AudioRendererSinkImpl::ConsumeFramesFunc(
-    int frames_consumed,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-    SbTime frames_consumed_at,
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-    void* context) {
+void AudioRendererSinkImpl::ConsumeFramesFunc(int frames_consumed,
+                                              SbTime frames_consumed_at,
+                                              void* context) {
   AudioRendererSinkImpl* audio_renderer_sink =
       static_cast<AudioRendererSinkImpl*>(context);
   SB_DCHECK(audio_renderer_sink);
   SB_DCHECK(audio_renderer_sink->render_callback_);
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-  audio_renderer_sink->render_callback_->ConsumeFrames(
-      frames_consumed,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-      kSbHasAsyncAudioFramesReporting ? frames_consumed_at
-                                      : (SbTime)kSbTimeMax);
-#else
-      frames_consumed_at);
-#endif
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-  audio_renderer_sink->render_callback_->ConsumeFrames(frames_consumed);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+  audio_renderer_sink->render_callback_->ConsumeFrames(frames_consumed,
+                                                       frames_consumed_at);
 }
 
 // static
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h b/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h
index 6b7650f..12fa6a6 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h
@@ -60,11 +60,7 @@
                                      bool* is_eos_reached,
                                      void* context);
   static void ConsumeFramesFunc(int frames_consumed,
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
                                 SbTime frames_consumed_at,
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
-        // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
                                 void* context);
   static void ErrorFunc(bool capability_changed, void* context);
 
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
index 6c9ff3e..c8efd9b 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
@@ -207,7 +207,6 @@
 }
 
 bool FilterBasedPlayerWorkerHandler::Seek(SbTime seek_to_time, int ticket) {
-  SB_UNREFERENCED_PARAMETER(ticket);
   SB_DCHECK(BelongsToCurrentThread());
 
   SB_LOG(INFO) << "Seek to " << seek_to_time << ", and media time provider is "
diff --git a/src/starboard/shared/starboard/player/filter/player_components.cc b/src/starboard/shared/starboard/player/filter/player_components.cc
index 1bee234..488c2dd 100644
--- a/src/starboard/shared/starboard/player/filter/player_components.cc
+++ b/src/starboard/shared/starboard/player/filter/player_components.cc
@@ -35,6 +35,10 @@
 
 namespace {
 
+const int kDefaultAudioSinkMinFramesPerAppend = 1024;
+const int kDefaultAudioSinkMaxCachedFrames =
+    8 * kDefaultAudioSinkMinFramesPerAppend;
+
 typedef MediaTimeProviderImpl::MonotonicSystemTimeProvider
     MonotonicSystemTimeProvider;
 
@@ -305,9 +309,8 @@
     int* min_frames_per_append) const {
   SB_DCHECK(max_cached_frames);
   SB_DCHECK(min_frames_per_append);
-
+  *min_frames_per_append = kDefaultAudioSinkMinFramesPerAppend;
 #if SB_API_VERSION >= 11
-  *min_frames_per_append = 1024;
   // AudioRenderer prefers to use kSbMediaAudioSampleTypeFloat32 and only uses
   // kSbMediaAudioSampleTypeInt16Deprecated when float32 is not supported.
   int min_frames_required = SbAudioSinkGetMinBufferSizeInFrames(
@@ -316,10 +319,14 @@
           ? kSbMediaAudioSampleTypeFloat32
           : kSbMediaAudioSampleTypeInt16Deprecated,
       creation_parameters.audio_sample_info().samples_per_second);
-  *max_cached_frames = min_frames_required + *min_frames_per_append * 2;
+  // Audio renderer would sleep for a while if it thinks there're enough
+  // frames in the sink. The sleeping time is 1/4 of |max_cached_frames|. So, to
+  // maintain required min buffer size of audio sink, the |max_cached_frames|
+  // need to be larger than |min_frames_required| * 4/3.
+  *max_cached_frames = static_cast<int>(min_frames_required * 1.4) +
+                       kDefaultAudioSinkMinFramesPerAppend;
 #else   // SB_API_VERSION >= 11
-  *max_cached_frames = 8 * 1024;
-  *min_frames_per_append = 1024;
+  *max_cached_frames = kDefaultAudioSinkMaxCachedFrames;
 #endif  // SB_API_VERSION >= 11
 }
 
diff --git a/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc b/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc
index ed80e22..2fa7fef 100644
--- a/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc
+++ b/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc
@@ -46,7 +46,6 @@
 
 void StubAudioDecoder::Initialize(const OutputCB& output_cb,
                                   const ErrorCB& error_cb) {
-  SB_UNREFERENCED_PARAMETER(error_cb);
   output_cb_ = output_cb;
 }
 
diff --git a/src/starboard/shared/starboard/player/filter/stub_video_decoder.cc b/src/starboard/shared/starboard/player/filter/stub_video_decoder.cc
index b680c0a..1827e2f 100644
--- a/src/starboard/shared/starboard/player/filter/stub_video_decoder.cc
+++ b/src/starboard/shared/starboard/player/filter/stub_video_decoder.cc
@@ -24,7 +24,6 @@
 
 void StubVideoDecoder::Initialize(const DecoderStatusCB& decoder_status_cb,
                                   const ErrorCB& error_cb) {
-  SB_UNREFERENCED_PARAMETER(error_cb);
   SB_DCHECK(decoder_status_cb);
   SB_DCHECK(!decoder_status_cb_);
   decoder_status_cb_ = decoder_status_cb;
diff --git a/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc b/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
index d3250c1..d5e9f2e 100644
--- a/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
@@ -83,8 +83,9 @@
                              }),
                              SaveArg<6>(&renderer_callback_)));
     ON_CALL(*audio_renderer_sink_, Stop())
-        .WillByDefault(InvokeWithoutArgs(
-            [this]() { audio_renderer_sink_->SetHasStarted(false); }));
+        .WillByDefault(InvokeWithoutArgs([this]() {
+          audio_renderer_sink_->SetHasStarted(false);
+        }));  // NOLINT
 
     ON_CALL(*audio_renderer_sink_, HasStarted())
         .WillByDefault(::testing::ReturnPointee(
@@ -273,7 +274,6 @@
   static void DeallocateSampleCB(SbPlayer player,
                                  void* context,
                                  const void* sample_buffer) {
-    SB_UNREFERENCED_PARAMETER(player);
     AudioRendererTest* test = static_cast<AudioRendererTest*>(context);
     EXPECT_TRUE(test != NULL);
     test->OnDeallocateSample(sample_buffer);
@@ -281,13 +281,19 @@
 };
 
 bool HasAsyncAudioFramesReporting() {
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  return kSbHasAsyncAudioFramesReporting;
-#elif SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
-  return true;
-#else
+#if SB_API_VERSION >= 12
+  // TODO: When deprecating Starboard API versions less than
+  // 12 it is safe to assume that all tests can be run regardless of
+  // whether the platform has asynchronous audio frames reporting.
+  // This function can be removed then.
   return false;
-#endif
+#else  // SB_API_VERSION >=  12
+#if SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+  return true;
+#else   // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+  return false;
+#endif  // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+#endif  // SB_API_VERSION >=  12
 }
 
 // static
@@ -307,9 +313,6 @@
   EXPECT_FALSE(is_eos_played);
 }
 
-// TODO: adapt these tests for async audio frames reporting.
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
-    !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 TEST_F(AudioRendererTest, SunnyDay) {
   if (HasAsyncAudioFramesReporting()) {
     SB_LOG(INFO) << "Platform has async audio frames reporting. Test skipped.";
@@ -365,11 +368,7 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(frames_to_consume, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(frames_to_consume);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_TRUE(is_playing);
@@ -378,11 +377,7 @@
   media_time = new_media_time;
 
   const int remaining_frames = frames_in_buffer - frames_to_consume;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(remaining_frames, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(remaining_frames);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_TRUE(is_playing);
@@ -459,22 +454,14 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(frames_to_consume, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(frames_to_consume);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_GT(new_media_time, media_time);
   media_time = new_media_time;
 
   const int remaining_frames = frames_in_buffer - frames_to_consume;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(remaining_frames, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(remaining_frames);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_GT(new_media_time, media_time);
@@ -529,11 +516,7 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(frames_to_consume, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(frames_to_consume);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_TRUE(is_playing);
@@ -542,11 +525,7 @@
   media_time = new_media_time;
 
   const int remaining_frames = frames_in_buffer - frames_to_consume;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(remaining_frames, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(remaining_frames);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_TRUE(is_playing);
@@ -716,11 +695,7 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(frames_to_consume, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(frames_to_consume);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_TRUE(is_playing);
@@ -729,11 +704,7 @@
   media_time = new_media_time;
 
   const int remaining_frames = frames_in_buffer - frames_to_consume;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(remaining_frames, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(remaining_frames);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_TRUE(is_playing);
@@ -817,22 +788,14 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(frames_to_consume, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(frames_to_consume);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_GE(new_media_time, media_time);
   media_time = new_media_time;
 
   const int remaining_frames = frames_in_buffer - frames_to_consume;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(remaining_frames, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(remaining_frames);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_GE(new_media_time, media_time);
@@ -898,11 +861,7 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(frames_to_consume, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(frames_to_consume);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_GE(new_media_time, media_time);
@@ -924,19 +883,13 @@
   EXPECT_GE(offset_in_frames, 0);
   EXPECT_TRUE(is_playing);
   EXPECT_TRUE(is_eos_reached);
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   renderer_callback_->ConsumeFrames(frames_in_buffer, SbTimeGetMonotonicNow());
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
-  renderer_callback_->ConsumeFrames(frames_in_buffer);
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
   new_media_time = audio_renderer_->GetCurrentMediaTime(
       &is_playing, &is_eos_played, &is_underflow);
   EXPECT_GE(new_media_time, seek_time);
 
   EXPECT_TRUE(audio_renderer_->IsEndOfStreamPlayed());
 }
-#endif  // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION &&
-        // !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
 
 // TODO: Add more Seek tests.
 
diff --git a/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp b/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp
index 507bc5f..bad4758 100644
--- a/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp
+++ b/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp
@@ -28,6 +28,8 @@
         '<(DEPTH)/starboard/shared/starboard/player/filter/testing/test_util.cc',
         '<(DEPTH)/starboard/shared/starboard/player/filter/testing/test_util.h',
         '<(DEPTH)/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc',
+        '<(DEPTH)/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.cc',
+        '<(DEPTH)/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.h',
         '<(DEPTH)/starboard/shared/starboard/player/filter/testing/video_frame_cadence_pattern_generator_test.cc',
         '<(DEPTH)/starboard/shared/starboard/player/filter/testing/video_frame_rate_estimator_test.cc',
         '<(DEPTH)/starboard/testing/fake_graphics_context_provider.cc',
diff --git a/src/starboard/shared/starboard/player/filter/testing/test_util.cc b/src/starboard/shared/starboard/player/filter/testing/test_util.cc
index 0d4181e..1207ea7 100644
--- a/src/starboard/shared/starboard/player/filter/testing/test_util.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/test_util.cc
@@ -32,6 +32,9 @@
 namespace testing {
 namespace {
 
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
 using video_dmp::VideoDmpReader;
 
 std::string GetTestInputDirectory() {
@@ -56,9 +59,6 @@
 void StubDeallocateSampleFunc(SbPlayer player,
                               void* context,
                               const void* sample_buffer) {
-  SB_UNREFERENCED_PARAMETER(player);
-  SB_UNREFERENCED_PARAMETER(context);
-  SB_UNREFERENCED_PARAMETER(sample_buffer);
 }
 
 std::string ResolveTestFileName(const char* filename) {
@@ -104,9 +104,9 @@
     VideoDmpReader dmp_reader(ResolveTestFileName(filename).c_str());
     SB_DCHECK(dmp_reader.number_of_audio_buffers() > 0);
     if (SbMediaIsAudioSupported(dmp_reader.audio_codec(),
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
                                 "",  // content_type
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
                                 dmp_reader.audio_bitrate())) {
       test_params_with_heaac.push_back(filename);
       if (SbStringFindString(filename, "heaac") == nullptr) {
@@ -155,9 +155,9 @@
 
       if (SbMediaIsVideoSupported(
               dmp_reader.video_codec(),
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
               "",  // content_type
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
 #if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
               -1, -1, 8, kSbMediaPrimaryIdUnspecified,
               kSbMediaTransferIdUnspecified, kSbMediaMatrixIdUnspecified,
@@ -168,7 +168,7 @@
               video_sample_info->frame_width, video_sample_info->frame_height,
 #endif  // SB_API_VERSION >= 11
               dmp_reader.video_bitrate(), dmp_reader.video_fps(), false)) {
-        test_params.push_back({filename, output_mode});
+        test_params.push_back(std::make_tuple(filename, output_mode));
       }
     }
   }
@@ -209,6 +209,36 @@
   return false;
 }
 
+AssertionResult AlmostEqualTime(SbTime time1, SbTime time2) {
+  const SbTime kEpsilon = kSbTimeSecond / 1000;
+  SbTime diff = time1 - time2;
+  if (-kEpsilon <= diff && diff <= kEpsilon) {
+    return AssertionSuccess();
+  }
+  return AssertionFailure()
+         << "time " << time1 << " doesn't match with time " << time2;
+}
+
+#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+media::VideoSampleInfo CreateVideoSampleInfo(SbMediaVideoCodec codec) {
+  shared::starboard::media::VideoSampleInfo video_sample_info = {};
+
+  video_sample_info.codec = codec;
+  video_sample_info.mime = "";
+  video_sample_info.max_video_capabilities = "";
+
+  video_sample_info.color_metadata.primaries = kSbMediaPrimaryIdBt709;
+  video_sample_info.color_metadata.transfer = kSbMediaTransferIdBt709;
+  video_sample_info.color_metadata.matrix = kSbMediaMatrixIdBt709;
+  video_sample_info.color_metadata.range = kSbMediaRangeIdLimited;
+
+  video_sample_info.frame_width = 1920;
+  video_sample_info.frame_height = 1080;
+
+  return video_sample_info;
+}
+#endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+
 }  // namespace testing
 }  // namespace filter
 }  // namespace player
diff --git a/src/starboard/shared/starboard/player/filter/testing/test_util.h b/src/starboard/shared/starboard/player/filter/testing/test_util.h
index 7002bf5..88ba4ca 100644
--- a/src/starboard/shared/starboard/player/filter/testing/test_util.h
+++ b/src/starboard/shared/starboard/player/filter/testing/test_util.h
@@ -16,6 +16,7 @@
 #define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_TESTING_TEST_UTIL_H_
 
 #include <string>
+#include <tuple>
 #include <utility>
 #include <vector>
 
@@ -23,6 +24,7 @@
 
 #include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
 #include "starboard/shared/starboard/player/filter/audio_renderer_sink.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 namespace starboard {
 namespace shared {
@@ -31,7 +33,7 @@
 namespace filter {
 namespace testing {
 
-typedef std::pair<const char*, SbPlayerOutputMode> VideoTestParam;
+typedef std::tuple<const char*, SbPlayerOutputMode> VideoTestParam;
 
 // The function doesn't free the buffer, it assumes that the lifetime of the
 // buffer is actually managed by other code.  It can be used in the places where
@@ -50,6 +52,12 @@
                            scoped_ptr<AudioDecoder>* audio_decoder,
                            scoped_ptr<AudioRendererSink>* audio_renderer_sink);
 
+::testing::AssertionResult AlmostEqualTime(SbTime time1, SbTime time2);
+
+#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+media::VideoSampleInfo CreateVideoSampleInfo(SbMediaVideoCodec codec);
+#endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+
 }  // namespace testing
 }  // namespace filter
 }  // namespace player
diff --git a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
index 8a51890..570ec86 100644
--- a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
@@ -31,6 +31,7 @@
 #include "starboard/shared/starboard/media/media_util.h"
 #include "starboard/shared/starboard/player/filter/stub_player_components_factory.h"
 #include "starboard/shared/starboard/player/filter/testing/test_util.h"
+#include "starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.h"
 #include "starboard/shared/starboard/player/job_queue.h"
 #include "starboard/shared/starboard/player/video_dmp_reader.h"
 #include "starboard/testing/fake_graphics_context_provider.h"
@@ -38,10 +39,6 @@
 #include "starboard/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-// This has to be defined in the global namespace as its instance will be used
-// as SbPlayer.
-struct SbPlayerPrivate {};
-
 namespace starboard {
 namespace shared {
 namespace starboard {
@@ -53,437 +50,42 @@
 using ::starboard::testing::FakeGraphicsContextProvider;
 using ::std::placeholders::_1;
 using ::std::placeholders::_2;
-using ::testing::AssertionFailure;
-using ::testing::AssertionResult;
-using ::testing::AssertionSuccess;
 using ::testing::Bool;
 using ::testing::Combine;
 using ::testing::ValuesIn;
-using video_dmp::VideoDmpReader;
-
-const SbTimeMonotonic kDefaultWaitForNextEventTimeOut = 5 * kSbTimeSecond;
-
-AssertionResult AlmostEqualTime(SbTime time1, SbTime time2) {
-  const SbTime kEpsilon = kSbTimeSecond / 1000;
-  SbTime diff = time1 - time2;
-  if (-kEpsilon <= diff && diff <= kEpsilon) {
-    return AssertionSuccess();
-  }
-  return AssertionFailure()
-         << "time " << time1 << " doesn't match with time " << time2;
-}
-
-#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-shared::starboard::media::VideoSampleInfo CreateVideoSampleInfo(
-    SbMediaVideoCodec codec) {
-  shared::starboard::media::VideoSampleInfo video_sample_info = {};
-
-  video_sample_info.codec = codec;
-  video_sample_info.mime = "";
-  video_sample_info.max_video_capabilities = "";
-
-  video_sample_info.color_metadata.primaries = kSbMediaPrimaryIdBt709;
-  video_sample_info.color_metadata.transfer = kSbMediaTransferIdBt709;
-  video_sample_info.color_metadata.matrix = kSbMediaMatrixIdBt709;
-  video_sample_info.color_metadata.range = kSbMediaRangeIdLimited;
-
-  video_sample_info.frame_width = 1920;
-  video_sample_info.frame_height = 1080;
-
-  return video_sample_info;
-}
-#endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 
 class VideoDecoderTest
     : public ::testing::TestWithParam<std::tuple<VideoTestParam, bool>> {
  public:
+  typedef VideoDecoderTestFixture::Event Event;
+  typedef VideoDecoderTestFixture::EventCB EventCB;
+  typedef VideoDecoderTestFixture::Status Status;
+
   VideoDecoderTest()
-      : test_filename_(std::get<0>(GetParam()).first),
-        output_mode_(std::get<0>(GetParam()).second),
-        using_stub_decoder_(std::get<1>(GetParam())),
-        dmp_reader_(ResolveTestFileName(test_filename_).c_str()) {
-    SB_LOG(INFO) << "Testing " << test_filename_ << ", output mode "
-                 << output_mode_
-                 << (using_stub_decoder_ ? " with stub video decoder." : ".");
-  }
+      : fixture_(&job_queue_,
+                 &fake_graphics_context_provider_,
+                 std::get<0>(std::get<0>(GetParam())),
+                 std::get<1>(std::get<0>(GetParam())),
+                 std::get<1>(GetParam())) {}
 
-  ~VideoDecoderTest() { video_decoder_->Reset(); }
-
-  void SetUp() override {
-    ASSERT_NE(dmp_reader_.video_codec(), kSbMediaVideoCodecNone);
-    ASSERT_GT(dmp_reader_.number_of_video_buffers(), 0);
-    ASSERT_TRUE(GetVideoInputBuffer(0)->video_sample_info().is_key_frame);
-
-    SbPlayerOutputMode output_mode = output_mode_;
-    ASSERT_TRUE(VideoDecoder::OutputModeSupported(
-        output_mode, dmp_reader_.video_codec(), kSbDrmSystemInvalid));
-
-    PlayerComponents::Factory::CreationParameters creation_parameters(
-        dmp_reader_.video_codec(),
-#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-        GetVideoInputBuffer(0)->video_sample_info(),
-#endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-        &player_, output_mode,
-        fake_graphics_context_provider_.decoder_target_provider(), nullptr);
-
-    scoped_ptr<PlayerComponents::Factory> factory;
-    if (using_stub_decoder_) {
-      factory = StubPlayerComponentsFactory::Create();
-    } else {
-      factory = PlayerComponents::Factory::Create();
-    }
-    std::string error_message;
-    ASSERT_TRUE(factory->CreateSubComponents(
-        creation_parameters, nullptr, nullptr, &video_decoder_,
-        &video_render_algorithm_, &video_renderer_sink_, &error_message));
-    ASSERT_TRUE(video_decoder_);
-
-    if (video_renderer_sink_) {
-      video_renderer_sink_->SetRenderCB(
-          std::bind(&VideoDecoderTest::Render, this, _1));
-    }
-
-    video_decoder_->Initialize(
-        std::bind(&VideoDecoderTest::OnDecoderStatusUpdate, this, _1, _2),
-        std::bind(&VideoDecoderTest::OnError, this));
-    if (HasPendingEvents()) {
-      bool error_occurred = false;
-      ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred));
-      ASSERT_FALSE(error_occurred);
-    }
-  }
-
-  void Render(VideoRendererSink::DrawFrameCB draw_frame_cb) {
-    SB_UNREFERENCED_PARAMETER(draw_frame_cb);
-  }
-
-  void OnDecoderStatusUpdate(VideoDecoder::Status status,
-                             const scoped_refptr<VideoFrame>& frame) {
-    ScopedLock scoped_lock(mutex_);
-    // TODO: Ensure that this is only called during dtor or Reset().
-    if (status == VideoDecoder::kReleaseAllFrames) {
-      SB_DCHECK(!frame);
-      event_queue_.clear();
-      decoded_frames_.clear();
-      return;
-    } else if (status == VideoDecoder::kNeedMoreInput) {
-      event_queue_.push_back(Event(kNeedMoreInput, frame));
-    } else if (status == VideoDecoder::kBufferFull) {
-      event_queue_.push_back(Event(kBufferFull, frame));
-    } else {
-      event_queue_.push_back(Event(kError, frame));
-    }
-  }
-
-  void OnError() {
-    ScopedLock scoped_lock(mutex_);
-    event_queue_.push_back(Event(kError, NULL));
-  }
-
-#if SB_HAS(GLES2)
-  void AssertInvalidDecodeTarget() {
-    if (output_mode_ == kSbPlayerOutputModeDecodeToTexture &&
-        !using_stub_decoder_) {
-      volatile bool is_decode_target_valid = true;
-      fake_graphics_context_provider_.RunOnGlesContextThread([&]() {
-        SbDecodeTarget decode_target = video_decoder_->GetCurrentDecodeTarget();
-        is_decode_target_valid = SbDecodeTargetIsValid(decode_target);
-        SbDecodeTargetRelease(decode_target);
-      });
-      ASSERT_FALSE(is_decode_target_valid);
-    }
-  }
-#endif  // SB_HAS(GLES2)
+  void SetUp() override { fixture_.Initialize(); }
 
  protected:
-  enum Status {
-    kNeedMoreInput = VideoDecoder::kNeedMoreInput,
-    kBufferFull = VideoDecoder::kBufferFull,
-    kError,
-    kTimeout
-  };
-
-  struct Event {
-    Status status;
-    scoped_refptr<VideoFrame> frame;
-
-    Event() : status(kNeedMoreInput) {}
-    Event(Status status, scoped_refptr<VideoFrame> frame)
-        : status(status), frame(frame) {}
-  };
-
-  // This function is called inside WriteMultipleInputs() whenever an event has
-  // been processed.
-  // |continue_process| will always be a valid pointer and always contains
-  // |true| when calling this callback.  The callback can set it to false to
-  // stop further processing.
-  typedef std::function<void(const Event&, bool* continue_process)> EventCB;
-
-  void WaitForNextEvent(
-      Event* event,
-      SbTimeMonotonic timeout = kDefaultWaitForNextEventTimeOut) {
-    ASSERT_TRUE(event);
-
-    SbTimeMonotonic start = SbTimeGetMonotonicNow();
-    while (SbTimeGetMonotonicNow() - start < timeout) {
-      job_queue_.RunUntilIdle();
-      GetDecodeTargetWhenSupported();
-      {
-        ScopedLock scoped_lock(mutex_);
-        if (!event_queue_.empty()) {
-          *event = event_queue_.front();
-          event_queue_.pop_front();
-          if (event->status == kNeedMoreInput) {
-            need_more_input_ = true;
-          } else if (event->status == kBufferFull) {
-            if (!end_of_stream_written_) {
-              ASSERT_FALSE(need_more_input_);
-            }
-          }
-          return;
-        }
-      }
-      SbThreadSleep(kSbTimeMillisecond);
-    }
-    event->status = kTimeout;
-  }
-
-  bool HasPendingEvents() {
-    const SbTime kDelay = 5 * kSbTimeMillisecond;
-    SbThreadSleep(kDelay);
-    ScopedLock scoped_lock(mutex_);
-    return !event_queue_.empty();
-  }
-
-  void GetDecodeTargetWhenSupported() {
-#if SB_HAS(GLES2)
-    if (output_mode_ == kSbPlayerOutputModeDecodeToTexture &&
-        !using_stub_decoder_) {
-      fake_graphics_context_provider_.RunOnGlesContextThread([&]() {
-        SbDecodeTargetRelease(video_decoder_->GetCurrentDecodeTarget());
-      });
-    }
-#endif  // SB_HAS(GLES2)
-  }
-
-  void AssertValidDecodeTargetWhenSupported() {
-#if SB_HAS(GLES2)
-    volatile bool is_decode_target_valid = false;
-    if (output_mode_ == kSbPlayerOutputModeDecodeToTexture &&
-        !using_stub_decoder_) {
-      fake_graphics_context_provider_.RunOnGlesContextThread([&]() {
-        SbDecodeTarget decode_target = video_decoder_->GetCurrentDecodeTarget();
-        is_decode_target_valid = SbDecodeTargetIsValid(decode_target);
-        SbDecodeTargetRelease(decode_target);
-      });
-      ASSERT_TRUE(is_decode_target_valid);
-    }
-#endif  // SB_HAS(GLES2)
-  }
-
-  // This has to be called when the decoder is just initialized/reseted or when
-  // status is |kNeedMoreInput|.
-  void WriteSingleInput(size_t index) {
-    ASSERT_TRUE(need_more_input_);
-    ASSERT_LT(index, dmp_reader_.number_of_video_buffers());
-
-    auto input_buffer = GetVideoInputBuffer(index);
-    {
-      ScopedLock scoped_lock(mutex_);
-      need_more_input_ = false;
-      outstanding_inputs_.insert(input_buffer->timestamp());
-    }
-
-    video_decoder_->WriteInputBuffer(input_buffer);
-  }
-
-  void WriteEndOfStream() {
-    {
-      ScopedLock scoped_lock(mutex_);
-      end_of_stream_written_ = true;
-    }
-    video_decoder_->WriteEndOfStream();
-  }
-
-  void WriteMultipleInputs(size_t start_index,
-                           size_t number_of_inputs_to_write,
-                           EventCB event_cb = EventCB()) {
-    ASSERT_LE(start_index + number_of_inputs_to_write,
-              dmp_reader_.number_of_video_buffers());
-
-    ASSERT_NO_FATAL_FAILURE(WriteSingleInput(start_index));
-    ++start_index;
-    --number_of_inputs_to_write;
-
-    while (number_of_inputs_to_write > 0) {
-      Event event;
-      ASSERT_NO_FATAL_FAILURE(WaitForNextEvent(&event));
-      if (event.status == kNeedMoreInput) {
-        ASSERT_NO_FATAL_FAILURE(WriteSingleInput(start_index));
-        ++start_index;
-        --number_of_inputs_to_write;
-      } else if (event.status == kError || event.status == kTimeout) {
-        // Assume that the caller does't expect an error when |event_cb| isn't
-        // provided.
-        ASSERT_TRUE(event_cb);
-        bool continue_process = true;
-        event_cb(event, &continue_process);
-        ASSERT_FALSE(continue_process);
-        return;
-      } else {
-        ASSERT_EQ(event.status, kBufferFull);
-      }
-      if (event.frame) {
-        ASSERT_FALSE(event.frame->is_end_of_stream());
-        if (!decoded_frames_.empty()) {
-          ASSERT_LT(decoded_frames_.back()->timestamp(),
-                    event.frame->timestamp());
-        }
-        decoded_frames_.push_back(event.frame);
-        ASSERT_TRUE(AlmostEqualTime(*outstanding_inputs_.begin(),
-                                    event.frame->timestamp()));
-        outstanding_inputs_.erase(outstanding_inputs_.begin());
-      }
-      if (event_cb) {
-        bool continue_process = true;
-        event_cb(event, &continue_process);
-        if (!continue_process) {
-          return;
-        }
-      }
-    }
-  }
-
-  void DrainOutputs(bool* error_occurred = NULL, EventCB event_cb = EventCB()) {
-    if (error_occurred) {
-      *error_occurred = false;
-    }
-
-    bool end_of_stream_decoded = false;
-
-    while (!end_of_stream_decoded) {
-      Event event;
-      ASSERT_NO_FATAL_FAILURE(WaitForNextEvent(&event));
-      if (event.status == kError || event.status == kTimeout) {
-        if (error_occurred) {
-          *error_occurred = true;
-        } else {
-          FAIL();
-        }
-        return;
-      }
-      if (event.frame) {
-        if (event.frame->is_end_of_stream()) {
-          end_of_stream_decoded = true;
-          if (!outstanding_inputs_.empty()) {
-            if (error_occurred) {
-              *error_occurred = true;
-            } else {
-              // |error_occurred| is NULL indicates that the caller doesn't
-              // expect an error, use the following redundant ASSERT to trigger
-              // a failure.
-              ASSERT_TRUE(outstanding_inputs_.empty());
-            }
-          }
-        } else {
-          if (!decoded_frames_.empty()) {
-            ASSERT_LT(decoded_frames_.back()->timestamp(),
-                      event.frame->timestamp());
-          }
-          decoded_frames_.push_back(event.frame);
-          ASSERT_TRUE(AlmostEqualTime(*outstanding_inputs_.begin(),
-                                      event.frame->timestamp()));
-          outstanding_inputs_.erase(outstanding_inputs_.begin());
-        }
-      }
-      if (event_cb) {
-        bool continue_process = true;
-        event_cb(event, &continue_process);
-        if (!continue_process) {
-          return;
-        }
-      }
-    }
-  }
-
-  void ResetDecoderAndClearPendingEvents() {
-    video_decoder_->Reset();
-    ScopedLock scoped_lock(mutex_);
-    event_queue_.clear();
-    need_more_input_ = true;
-    end_of_stream_written_ = false;
-    outstanding_inputs_.clear();
-    decoded_frames_.clear();
-  }
-
-  scoped_refptr<InputBuffer> GetVideoInputBuffer(size_t index) const {
-    auto video_sample_info =
-        dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeVideo, index);
-#if SB_API_VERSION >= 11
-    auto input_buffer = new InputBuffer(StubDeallocateSampleFunc, NULL, NULL,
-                                        video_sample_info);
-#else   // SB_API_VERSION >= 11
-    auto input_buffer =
-        new InputBuffer(kSbMediaTypeVideo, StubDeallocateSampleFunc, NULL, NULL,
-                        video_sample_info, NULL);
-#endif  // SB_API_VERSION >= 11
-    auto iter = invalid_inputs_.find(index);
-    if (iter != invalid_inputs_.end()) {
-      std::vector<uint8_t> content(input_buffer->size(), iter->second);
-      // Replace the content with invalid data.
-      input_buffer->SetDecryptedContent(content.data(),
-                                        static_cast<int>(content.size()));
-    }
-    return input_buffer;
-  }
-
-  void UseInvalidDataForInput(size_t index, uint8_t byte_to_fill) {
-    invalid_inputs_[index] = byte_to_fill;
-  }
-
   JobQueue job_queue_;
-
-  Mutex mutex_;
-  std::deque<Event> event_queue_;
-
-  // Test parameter filename for the VideoDmpReader to load and test with.
-  const char* test_filename_;
-
-  // Test parameter for OutputMode.
-  SbPlayerOutputMode output_mode_;
-
-  // Test parameter for whether or not to use the StubVideoDecoder, or the
-  // platform-specific VideoDecoderImpl.
-  bool using_stub_decoder_;
-
   FakeGraphicsContextProvider fake_graphics_context_provider_;
-  VideoDmpReader dmp_reader_;
-  scoped_ptr<VideoDecoder> video_decoder_;
-
-  bool need_more_input_ = true;
-  std::set<SbTime> outstanding_inputs_;
-  std::deque<scoped_refptr<VideoFrame>> decoded_frames_;
-
- private:
-  SbPlayerPrivate player_;
-  scoped_ptr<VideoRenderAlgorithm> video_render_algorithm_;
-  scoped_refptr<VideoRendererSink> video_renderer_sink_;
-
-  bool end_of_stream_written_ = false;
-
-  std::map<size_t, uint8_t> invalid_inputs_;
+  VideoDecoderTestFixture fixture_;
 };
 
 TEST_P(VideoDecoderTest, PrerollFrameCount) {
-  EXPECT_GT(video_decoder_->GetPrerollFrameCount(), 0);
+  EXPECT_GT(fixture_.video_decoder()->GetPrerollFrameCount(), 0);
 }
 
 TEST_P(VideoDecoderTest, MaxNumberOfCachedFrames) {
-  EXPECT_GT(video_decoder_->GetMaxNumberOfCachedFrames(), 1);
+  EXPECT_GT(fixture_.video_decoder()->GetMaxNumberOfCachedFrames(), 1);
 }
 
 TEST_P(VideoDecoderTest, PrerollTimeout) {
-  EXPECT_GE(video_decoder_->GetPrerollTimeout(), 0);
+  EXPECT_GE(fixture_.video_decoder()->GetPrerollTimeout(), 0);
 }
 
 // Ensure that OutputModeSupported() is callable on all combinations.
@@ -515,8 +117,8 @@
 
 #if SB_HAS(GLES2)
 TEST_P(VideoDecoderTest, GetCurrentDecodeTargetBeforeWriteInputBuffer) {
-  if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) {
-    AssertInvalidDecodeTarget();
+  if (fixture_.output_mode() == kSbPlayerOutputModeDecodeToTexture) {
+    fixture_.AssertInvalidDecodeTarget();
   }
 }
 #endif  // SB_HAS(GLES2)
@@ -564,9 +166,9 @@
 #endif  // SB_API_VERSION >= 11
           };
           PlayerComponents::Factory::CreationParameters creation_parameters(
-              dmp_reader_.video_codec(),
+              fixture_.dmp_reader().video_codec(),
 #if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-              CreateVideoSampleInfo(dmp_reader_.video_codec()),
+              CreateVideoSampleInfo(fixture_.dmp_reader().video_codec()),
 #endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
               &players[i], output_mode,
               fake_graphics_context_provider_.decoder_target_provider(),
@@ -581,22 +183,23 @@
 
           if (video_renderer_sinks[i]) {
             video_renderer_sinks[i]->SetRenderCB(
-                std::bind(&VideoDecoderTest::Render, this, _1));
+                std::bind(&VideoDecoderTestFixture::Render, &fixture_, _1));
           }
 
           video_decoders[i]->Initialize(
-              std::bind(&VideoDecoderTest::OnDecoderStatusUpdate, this, _1, _2),
-              std::bind(&VideoDecoderTest::OnError, this));
+              std::bind(&VideoDecoderTestFixture::OnDecoderStatusUpdate,
+                        &fixture_, _1, _2),
+              std::bind(&VideoDecoderTestFixture::OnError, &fixture_));
 
 #if SB_HAS(GLES2)
           if (output_mode == kSbPlayerOutputModeDecodeToTexture) {
-            AssertInvalidDecodeTarget();
+            fixture_.AssertInvalidDecodeTarget();
           }
 #endif  // SB_HAS(GLES2)
         }
-        if (HasPendingEvents()) {
+        if (fixture_.HasPendingEvents()) {
           bool error_occurred = false;
-          ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred));
+          ASSERT_NO_FATAL_FAILURE(fixture_.DrainOutputs(&error_occurred));
           ASSERT_FALSE(error_occurred);
         }
       }
@@ -605,11 +208,11 @@
 }
 
 TEST_P(VideoDecoderTest, SingleInput) {
-  WriteSingleInput(0);
-  WriteEndOfStream();
+  fixture_.WriteSingleInput(0);
+  fixture_.WriteEndOfStream();
 
   bool error_occurred = false;
-  ASSERT_NO_FATAL_FAILURE(DrainOutputs(
+  ASSERT_NO_FATAL_FAILURE(fixture_.DrainOutputs(
       &error_occurred, [=](const Event& event, bool* continue_process) {
         if (event.frame) {
           // TODO: On some platforms, decode texture will be ready only after
@@ -623,194 +226,203 @@
 }
 
 TEST_P(VideoDecoderTest, SingleInvalidKeyFrame) {
-  UseInvalidDataForInput(0, 0xab);
+  fixture_.UseInvalidDataForInput(0, 0xab);
 
-  WriteSingleInput(0);
-  WriteEndOfStream();
+  fixture_.WriteSingleInput(0);
+  fixture_.WriteEndOfStream();
 
   bool error_occurred = true;
-  ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred));
+  ASSERT_NO_FATAL_FAILURE(fixture_.DrainOutputs(&error_occurred));
   // We don't expect the video decoder can always recover from a bad key frame
   // and to raise an error, but it shouldn't crash or hang.
-  GetDecodeTargetWhenSupported();
+  fixture_.GetDecodeTargetWhenSupported();
 }
 
 TEST_P(VideoDecoderTest, MultipleValidInputsAfterInvalidKeyFrame) {
   const size_t kMaxNumberOfInputToWrite = 10;
   const size_t number_of_input_to_write =
-      std::min(kMaxNumberOfInputToWrite, dmp_reader_.number_of_video_buffers());
+      std::min(kMaxNumberOfInputToWrite,
+               fixture_.dmp_reader().number_of_video_buffers());
 
-  UseInvalidDataForInput(0, 0xab);
+  fixture_.UseInvalidDataForInput(0, 0xab);
 
   bool error_occurred = false;
   bool timeout_occurred = false;
   // Write first few frames.  The first one is invalid and the rest are valid.
-  WriteMultipleInputs(0, number_of_input_to_write,
-                      [&](const Event& event, bool* continue_process) {
-                        if (event.status == kTimeout) {
-                          timeout_occurred = true;
-                          *continue_process = false;
-                          return;
-                        }
-                        if (event.status == kError) {
-                          error_occurred = true;
-                          *continue_process = false;
-                          return;
-                        }
-                        *continue_process = event.status != kBufferFull;
-                      });
+  fixture_.WriteMultipleInputs(0, number_of_input_to_write,
+                               [&](const Event& event, bool* continue_process) {
+                                 if (event.status == Status::kTimeout) {
+                                   timeout_occurred = true;
+                                   *continue_process = false;
+                                   return;
+                                 }
+                                 if (event.status == Status::kError) {
+                                   error_occurred = true;
+                                   *continue_process = false;
+                                   return;
+                                 }
+                                 *continue_process =
+                                     event.status != Status::kBufferFull;
+                               });
   ASSERT_FALSE(timeout_occurred);
   if (!error_occurred) {
-    GetDecodeTargetWhenSupported();
-    WriteEndOfStream();
-    ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred));
+    fixture_.GetDecodeTargetWhenSupported();
+    fixture_.WriteEndOfStream();
+    ASSERT_NO_FATAL_FAILURE(fixture_.DrainOutputs(&error_occurred));
   }
   // We don't expect the video decoder can always recover from a bad key frame
   // and to raise an error, but it shouldn't crash or hang.
-  GetDecodeTargetWhenSupported();
+  fixture_.GetDecodeTargetWhenSupported();
 }
 
 TEST_P(VideoDecoderTest, MultipleInvalidInput) {
   const size_t kMaxNumberOfInputToWrite = 128;
   const size_t number_of_input_to_write =
-      std::min(kMaxNumberOfInputToWrite, dmp_reader_.number_of_video_buffers());
+      std::min(kMaxNumberOfInputToWrite,
+               fixture_.dmp_reader().number_of_video_buffers());
   // Replace the content of the first few input buffers with invalid data.
   // Every test instance loads its own copy of data so this won't affect other
   // tests.
   for (size_t i = 0; i < number_of_input_to_write; ++i) {
-    UseInvalidDataForInput(i, static_cast<uint8_t>(0xab + i));
+    fixture_.UseInvalidDataForInput(i, static_cast<uint8_t>(0xab + i));
   }
 
   bool error_occurred = false;
   bool timeout_occurred = false;
-  WriteMultipleInputs(0, number_of_input_to_write,
-                      [&](const Event& event, bool* continue_process) {
-                        if (event.status == kTimeout) {
-                          timeout_occurred = true;
-                          *continue_process = false;
-                          return;
-                        }
-                        if (event.status == kError) {
-                          error_occurred = true;
-                          *continue_process = false;
-                          return;
-                        }
+  fixture_.WriteMultipleInputs(0, number_of_input_to_write,
+                               [&](const Event& event, bool* continue_process) {
+                                 if (event.status == Status::kTimeout) {
+                                   timeout_occurred = true;
+                                   *continue_process = false;
+                                   return;
+                                 }
+                                 if (event.status == Status::kError) {
+                                   error_occurred = true;
+                                   *continue_process = false;
+                                   return;
+                                 }
 
-                        *continue_process = event.status != kBufferFull;
-                      });
+                                 *continue_process =
+                                     event.status != Status::kBufferFull;
+                               });
   ASSERT_FALSE(timeout_occurred);
   if (!error_occurred) {
-    GetDecodeTargetWhenSupported();
-    WriteEndOfStream();
-    ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred));
+    fixture_.GetDecodeTargetWhenSupported();
+    fixture_.WriteEndOfStream();
+    ASSERT_NO_FATAL_FAILURE(fixture_.DrainOutputs(&error_occurred));
   }
   // We don't expect the video decoder can always recover from a bad key frame
   // and to raise an error, but it shouldn't crash or hang.
-  GetDecodeTargetWhenSupported();
+  fixture_.GetDecodeTargetWhenSupported();
 }
 
 TEST_P(VideoDecoderTest, EndOfStreamWithoutAnyInput) {
-  WriteEndOfStream();
-  ASSERT_NO_FATAL_FAILURE(DrainOutputs());
+  fixture_.WriteEndOfStream();
+  ASSERT_NO_FATAL_FAILURE(fixture_.DrainOutputs());
 }
 
 TEST_P(VideoDecoderTest, ResetBeforeInput) {
-  EXPECT_FALSE(HasPendingEvents());
-  ResetDecoderAndClearPendingEvents();
-  EXPECT_FALSE(HasPendingEvents());
+  EXPECT_FALSE(fixture_.HasPendingEvents());
+  fixture_.ResetDecoderAndClearPendingEvents();
+  EXPECT_FALSE(fixture_.HasPendingEvents());
 
-  WriteSingleInput(0);
-  WriteEndOfStream();
-  ASSERT_NO_FATAL_FAILURE(DrainOutputs());
+  fixture_.WriteSingleInput(0);
+  fixture_.WriteEndOfStream();
+  ASSERT_NO_FATAL_FAILURE(fixture_.DrainOutputs());
 }
 
 TEST_P(VideoDecoderTest, ResetAfterInput) {
   const size_t max_inputs_to_write =
-      std::min<size_t>(dmp_reader_.number_of_video_buffers(), 10);
+      std::min<size_t>(fixture_.dmp_reader().number_of_video_buffers(), 10);
   bool error_occurred = false;
-  WriteMultipleInputs(
+  fixture_.WriteMultipleInputs(
       0, max_inputs_to_write, [&](const Event& event, bool* continue_process) {
-        if (event.status == kTimeout || event.status == kError) {
+        if (event.status == Status::kTimeout ||
+            event.status == Status::kError) {
           error_occurred = true;
           *continue_process = false;
           return;
         }
-        *continue_process = event.status != kBufferFull;
+        *continue_process = event.status != Status::kBufferFull;
       });
   ASSERT_FALSE(error_occurred);
-  ResetDecoderAndClearPendingEvents();
-  EXPECT_FALSE(HasPendingEvents());
+  fixture_.ResetDecoderAndClearPendingEvents();
+  EXPECT_FALSE(fixture_.HasPendingEvents());
 }
 
 TEST_P(VideoDecoderTest, MultipleResets) {
   const size_t max_inputs_to_write =
-      std::min<size_t>(dmp_reader_.number_of_video_buffers(), 10);
+      std::min<size_t>(fixture_.dmp_reader().number_of_video_buffers(), 10);
   for (int max_inputs = 1; max_inputs < max_inputs_to_write; ++max_inputs) {
     bool error_occurred = false;
-    WriteMultipleInputs(
+    fixture_.WriteMultipleInputs(
         0, max_inputs, [&](const Event& event, bool* continue_process) {
-          if (event.status == kTimeout || event.status == kError) {
+          if (event.status == Status::kTimeout ||
+              event.status == Status::kError) {
             error_occurred = true;
             *continue_process = false;
             return;
           }
-          *continue_process = event.status != kBufferFull;
+          *continue_process = event.status != Status::kBufferFull;
         });
     ASSERT_FALSE(error_occurred);
-    ResetDecoderAndClearPendingEvents();
-    EXPECT_FALSE(HasPendingEvents());
-    WriteSingleInput(0);
-    WriteEndOfStream();
-    ASSERT_NO_FATAL_FAILURE(DrainOutputs());
-    ResetDecoderAndClearPendingEvents();
-    EXPECT_FALSE(HasPendingEvents());
+    fixture_.ResetDecoderAndClearPendingEvents();
+    EXPECT_FALSE(fixture_.HasPendingEvents());
+    fixture_.WriteSingleInput(0);
+    fixture_.WriteEndOfStream();
+    ASSERT_NO_FATAL_FAILURE(fixture_.DrainOutputs());
+    fixture_.ResetDecoderAndClearPendingEvents();
+    EXPECT_FALSE(fixture_.HasPendingEvents());
   }
 }
 
 TEST_P(VideoDecoderTest, MultipleInputs) {
   const size_t kMaxNumberOfExpectedDecodedFrames = 5;
-  const size_t number_of_expected_decoded_frames = std::min(
-      kMaxNumberOfExpectedDecodedFrames, dmp_reader_.number_of_video_buffers());
+  const size_t number_of_expected_decoded_frames =
+      std::min(kMaxNumberOfExpectedDecodedFrames,
+               fixture_.dmp_reader().number_of_video_buffers());
   size_t frames_decoded = 0;
   bool error_occurred = false;
-  ASSERT_NO_FATAL_FAILURE(WriteMultipleInputs(
-      0, dmp_reader_.number_of_video_buffers(),
+  ASSERT_NO_FATAL_FAILURE(fixture_.WriteMultipleInputs(
+      0, fixture_.dmp_reader().number_of_video_buffers(),
       [&](const Event& event, bool* continue_process) {
-        if (event.status == kTimeout || event.status == kError) {
+        if (event.status == Status::kTimeout ||
+            event.status == Status::kError) {
           error_occurred = true;
           *continue_process = false;
           return;
         }
-        frames_decoded += decoded_frames_.size();
-        decoded_frames_.clear();
+        frames_decoded += fixture_.GetDecodedFramesCount();
+        fixture_.ClearDecodedFrames();
         *continue_process = frames_decoded < number_of_expected_decoded_frames;
       }));
   ASSERT_FALSE(error_occurred);
   if (frames_decoded < number_of_expected_decoded_frames) {
-    WriteEndOfStream();
-    ASSERT_NO_FATAL_FAILURE(DrainOutputs());
+    fixture_.WriteEndOfStream();
+    ASSERT_NO_FATAL_FAILURE(fixture_.DrainOutputs());
   }
 }
 
 TEST_P(VideoDecoderTest, Preroll) {
   SbTimeMonotonic start = SbTimeGetMonotonicNow();
-  SbTime preroll_timeout = video_decoder_->GetPrerollTimeout();
+  SbTime preroll_timeout = fixture_.video_decoder()->GetPrerollTimeout();
   bool error_occurred = false;
-  ASSERT_NO_FATAL_FAILURE(WriteMultipleInputs(
-      0, dmp_reader_.number_of_video_buffers(),
+  ASSERT_NO_FATAL_FAILURE(fixture_.WriteMultipleInputs(
+      0, fixture_.dmp_reader().number_of_video_buffers(),
       [&](const Event& event, bool* continue_process) {
-        if (event.status == kError) {
+        if (event.status == Status::kError) {
           error_occurred = true;
           *continue_process = false;
           return;
         }
-        if (decoded_frames_.size() >= video_decoder_->GetPrerollFrameCount()) {
+        if (fixture_.GetDecodedFramesCount() >=
+            fixture_.video_decoder()->GetPrerollFrameCount()) {
           *continue_process = false;
           return;
         }
         if (SbTimeGetMonotonicNow() - start >= preroll_timeout) {
           // After preroll timeout, we should get at least 1 decoded frame.
-          ASSERT_GT(decoded_frames_.size(), 0);
+          ASSERT_GT(fixture_.GetDecodedFramesCount(), 0);
           *continue_process = false;
           return;
         }
@@ -822,60 +434,67 @@
 
 TEST_P(VideoDecoderTest, HoldFramesUntilFull) {
   bool error_occurred = false;
-  ASSERT_NO_FATAL_FAILURE(WriteMultipleInputs(
-      0, dmp_reader_.number_of_video_buffers(),
+  ASSERT_NO_FATAL_FAILURE(fixture_.WriteMultipleInputs(
+      0, fixture_.dmp_reader().number_of_video_buffers(),
       [&](const Event& event, bool* continue_process) {
-        if (event.status == kTimeout || event.status == kError) {
+        if (event.status == Status::kTimeout ||
+            event.status == Status::kError) {
           error_occurred = true;
           *continue_process = false;
           return;
         }
-        *continue_process = decoded_frames_.size() <
-                            video_decoder_->GetMaxNumberOfCachedFrames();
+        *continue_process =
+            fixture_.GetDecodedFramesCount() <
+            fixture_.video_decoder()->GetMaxNumberOfCachedFrames();
       }));
   ASSERT_FALSE(error_occurred);
-  WriteEndOfStream();
-  if (decoded_frames_.size() >= video_decoder_->GetMaxNumberOfCachedFrames()) {
+  fixture_.WriteEndOfStream();
+  if (fixture_.GetDecodedFramesCount() >=
+      fixture_.video_decoder()->GetMaxNumberOfCachedFrames()) {
     return;
   }
-  ASSERT_NO_FATAL_FAILURE(DrainOutputs(
+  ASSERT_NO_FATAL_FAILURE(fixture_.DrainOutputs(
       &error_occurred, [=](const Event& event, bool* continue_process) {
-        *continue_process = decoded_frames_.size() <
-                            video_decoder_->GetMaxNumberOfCachedFrames();
+        *continue_process =
+            fixture_.GetDecodedFramesCount() <
+            fixture_.video_decoder()->GetMaxNumberOfCachedFrames();
       }));
   ASSERT_FALSE(error_occurred);
 }
 
 TEST_P(VideoDecoderTest, DecodeFullGOP) {
   int gop_size = 1;
-  while (gop_size < dmp_reader_.number_of_video_buffers()) {
-    if (GetVideoInputBuffer(gop_size)->video_sample_info().is_key_frame) {
+  while (gop_size < fixture_.dmp_reader().number_of_video_buffers()) {
+    if (fixture_.GetVideoInputBuffer(gop_size)
+            ->video_sample_info()
+            .is_key_frame) {
       break;
     }
     ++gop_size;
   }
   bool error_occurred = false;
-  ASSERT_NO_FATAL_FAILURE(WriteMultipleInputs(
+  ASSERT_NO_FATAL_FAILURE(fixture_.WriteMultipleInputs(
       0, gop_size, [&](const Event& event, bool* continue_process) {
-        if (event.status == kTimeout || event.status == kError) {
+        if (event.status == Status::kTimeout ||
+            event.status == Status::kError) {
           error_occurred = true;
           *continue_process = false;
           return;
         }
         // Keep 1 decoded frame, assuming it's used by renderer.
-        while (decoded_frames_.size() > 1) {
-          decoded_frames_.pop_front();
+        while (fixture_.GetDecodedFramesCount() > 1) {
+          fixture_.PopDecodedFrame();
         }
         *continue_process = true;
       }));
   ASSERT_FALSE(error_occurred);
-  WriteEndOfStream();
+  fixture_.WriteEndOfStream();
 
-  ASSERT_NO_FATAL_FAILURE(DrainOutputs(
+  ASSERT_NO_FATAL_FAILURE(fixture_.DrainOutputs(
       &error_occurred, [=](const Event& event, bool* continue_process) {
         // Keep 1 decoded frame, assuming it's used by renderer.
-        while (decoded_frames_.size() > 1) {
-          decoded_frames_.pop_front();
+        while (fixture_.GetDecodedFramesCount() > 1) {
+          fixture_.PopDecodedFrame();
         }
         *continue_process = true;
       }));
diff --git a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.cc b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.cc
new file mode 100644
index 0000000..f680f11
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.cc
@@ -0,0 +1,387 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.h"
+
+#include <algorithm>
+#include <deque>
+#include <functional>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "starboard/common/condition_variable.h"
+#include "starboard/common/mutex.h"
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/common/string.h"
+#include "starboard/configuration_constants.h"
+#include "starboard/drm.h"
+#include "starboard/media.h"
+#include "starboard/memory.h"
+#include "starboard/shared/starboard/media/media_util.h"
+#include "starboard/shared/starboard/player/filter/stub_player_components_factory.h"
+#include "starboard/shared/starboard/player/filter/testing/test_util.h"
+#include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
+#include "starboard/shared/starboard/player/job_queue.h"
+#include "starboard/shared/starboard/player/video_dmp_reader.h"
+#include "starboard/testing/fake_graphics_context_provider.h"
+#include "starboard/thread.h"
+#include "starboard/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+namespace testing {
+namespace {
+
+using ::starboard::testing::FakeGraphicsContextProvider;
+using ::std::placeholders::_1;
+using ::std::placeholders::_2;
+using video_dmp::VideoDmpReader;
+
+}  // namespace
+
+VideoDecoderTestFixture::VideoDecoderTestFixture(
+    JobQueue* job_queue,
+    FakeGraphicsContextProvider* fake_graphics_context_provider,
+    const char* test_filename,
+    SbPlayerOutputMode output_mode,
+    bool using_stub_decoder)
+    : job_queue_(job_queue),
+      fake_graphics_context_provider_(fake_graphics_context_provider),
+      test_filename_(test_filename),
+      output_mode_(output_mode),
+      using_stub_decoder_(using_stub_decoder),
+      dmp_reader_(ResolveTestFileName(test_filename).c_str()) {
+  SB_DCHECK(job_queue_);
+  SB_DCHECK(fake_graphics_context_provider_);
+  SB_LOG(INFO) << "Testing " << test_filename_ << ", output mode "
+               << output_mode_
+               << (using_stub_decoder_ ? " with stub video decoder." : ".");
+}
+
+void VideoDecoderTestFixture::Initialize() {
+  ASSERT_NE(dmp_reader_.video_codec(), kSbMediaVideoCodecNone);
+  ASSERT_GT(dmp_reader_.number_of_video_buffers(), 0);
+  ASSERT_TRUE(GetVideoInputBuffer(0)->video_sample_info().is_key_frame);
+
+  SbPlayerOutputMode output_mode = output_mode_;
+  ASSERT_TRUE(VideoDecoder::OutputModeSupported(
+      output_mode, dmp_reader_.video_codec(), kSbDrmSystemInvalid));
+
+  PlayerComponents::Factory::CreationParameters creation_parameters(
+      dmp_reader_.video_codec(),
+#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+      GetVideoInputBuffer(0)->video_sample_info(),
+#endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+      &player_, output_mode,
+      fake_graphics_context_provider_->decoder_target_provider(), nullptr);
+
+  scoped_ptr<PlayerComponents::Factory> factory;
+  if (using_stub_decoder_) {
+    factory = StubPlayerComponentsFactory::Create();
+  } else {
+    factory = PlayerComponents::Factory::Create();
+  }
+  std::string error_message;
+  ASSERT_TRUE(factory->CreateSubComponents(
+      creation_parameters, nullptr, nullptr, &video_decoder_,
+      &video_render_algorithm_, &video_renderer_sink_, &error_message));
+  ASSERT_TRUE(video_decoder_);
+
+  if (video_renderer_sink_) {
+    video_renderer_sink_->SetRenderCB(
+        std::bind(&VideoDecoderTestFixture::Render, this, _1));
+  }
+
+  video_decoder_->Initialize(
+      std::bind(&VideoDecoderTestFixture::OnDecoderStatusUpdate, this, _1, _2),
+      std::bind(&VideoDecoderTestFixture::OnError, this));
+  if (HasPendingEvents()) {
+    bool error_occurred = false;
+    ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred));
+    ASSERT_FALSE(error_occurred);
+  }
+}
+
+void VideoDecoderTestFixture::OnDecoderStatusUpdate(
+    VideoDecoder::Status status,
+    const scoped_refptr<VideoFrame>& frame) {
+  ScopedLock scoped_lock(mutex_);
+  // TODO: Ensure that this is only called during dtor or Reset().
+  if (status == VideoDecoder::kReleaseAllFrames) {
+    SB_DCHECK(!frame);
+    event_queue_.clear();
+    decoded_frames_.clear();
+    return;
+  } else if (status == VideoDecoder::kNeedMoreInput) {
+    event_queue_.push_back(Event(kNeedMoreInput, frame));
+  } else if (status == VideoDecoder::kBufferFull) {
+    event_queue_.push_back(Event(kBufferFull, frame));
+  } else {
+    event_queue_.push_back(Event(kError, frame));
+  }
+}
+
+void VideoDecoderTestFixture::OnError() {
+  ScopedLock scoped_lock(mutex_);
+  event_queue_.push_back(Event(kError, NULL));
+}
+
+#if SB_HAS(GLES2)
+void VideoDecoderTestFixture::AssertInvalidDecodeTarget() {
+  if (output_mode_ == kSbPlayerOutputModeDecodeToTexture &&
+      !using_stub_decoder_) {
+    volatile bool is_decode_target_valid = true;
+    fake_graphics_context_provider_->RunOnGlesContextThread([&]() {
+      SbDecodeTarget decode_target = video_decoder_->GetCurrentDecodeTarget();
+      is_decode_target_valid = SbDecodeTargetIsValid(decode_target);
+      SbDecodeTargetRelease(decode_target);
+    });
+    ASSERT_FALSE(is_decode_target_valid);
+  }
+}
+#endif  // SB_HAS(GLES2)
+
+void VideoDecoderTestFixture::WaitForNextEvent(Event* event,
+                                               SbTimeMonotonic timeout) {
+  ASSERT_TRUE(event);
+
+  SbTimeMonotonic start = SbTimeGetMonotonicNow();
+  do {
+    job_queue_->RunUntilIdle();
+    GetDecodeTargetWhenSupported();
+    {
+      ScopedLock scoped_lock(mutex_);
+      if (!event_queue_.empty()) {
+        *event = event_queue_.front();
+        event_queue_.pop_front();
+        if (event->status == kNeedMoreInput) {
+          need_more_input_ = true;
+        } else if (event->status == kBufferFull) {
+          if (!end_of_stream_written_) {
+            ASSERT_FALSE(need_more_input_);
+          }
+        }
+        return;
+      }
+    }
+    SbThreadSleep(kSbTimeMillisecond);
+  } while (SbTimeGetMonotonicNow() - start < timeout);
+  event->status = kTimeout;
+}
+
+bool VideoDecoderTestFixture::HasPendingEvents() {
+  const SbTime kDelay = 5 * kSbTimeMillisecond;
+  SbThreadSleep(kDelay);
+  ScopedLock scoped_lock(mutex_);
+  return !event_queue_.empty();
+}
+
+void VideoDecoderTestFixture::GetDecodeTargetWhenSupported() {
+#if SB_HAS(GLES2)
+  if (output_mode_ == kSbPlayerOutputModeDecodeToTexture &&
+      !using_stub_decoder_) {
+    fake_graphics_context_provider_->RunOnGlesContextThread([&]() {
+      SbDecodeTargetRelease(video_decoder_->GetCurrentDecodeTarget());
+    });
+  }
+#endif  // SB_HAS(GLES2)
+}
+
+void VideoDecoderTestFixture::AssertValidDecodeTargetWhenSupported() {
+#if SB_HAS(GLES2)
+  volatile bool is_decode_target_valid = false;
+  if (output_mode_ == kSbPlayerOutputModeDecodeToTexture &&
+      !using_stub_decoder_) {
+    fake_graphics_context_provider_->RunOnGlesContextThread([&]() {
+      SbDecodeTarget decode_target = video_decoder_->GetCurrentDecodeTarget();
+      is_decode_target_valid = SbDecodeTargetIsValid(decode_target);
+      SbDecodeTargetRelease(decode_target);
+    });
+    ASSERT_TRUE(is_decode_target_valid);
+  }
+#endif  // SB_HAS(GLES2)
+}
+
+// This has to be called when the decoder is just initialized/reseted or when
+// status is |kNeedMoreInput|.
+void VideoDecoderTestFixture::WriteSingleInput(size_t index) {
+  ASSERT_TRUE(need_more_input_);
+  ASSERT_LT(index, dmp_reader_.number_of_video_buffers());
+
+  auto input_buffer = GetVideoInputBuffer(index);
+  {
+    ScopedLock scoped_lock(mutex_);
+    need_more_input_ = false;
+    outstanding_inputs_.insert(input_buffer->timestamp());
+  }
+
+  video_decoder_->WriteInputBuffer(input_buffer);
+}
+
+void VideoDecoderTestFixture::WriteEndOfStream() {
+  {
+    ScopedLock scoped_lock(mutex_);
+    end_of_stream_written_ = true;
+  }
+  video_decoder_->WriteEndOfStream();
+}
+
+void VideoDecoderTestFixture::WriteMultipleInputs(
+    size_t start_index,
+    size_t number_of_inputs_to_write,
+    EventCB event_cb) {
+  ASSERT_LE(start_index + number_of_inputs_to_write,
+            dmp_reader_.number_of_video_buffers());
+
+  ASSERT_NO_FATAL_FAILURE(WriteSingleInput(start_index));
+  ++start_index;
+  --number_of_inputs_to_write;
+
+  while (number_of_inputs_to_write > 0) {
+    Event event;
+    ASSERT_NO_FATAL_FAILURE(WaitForNextEvent(&event));
+    if (event.status == kNeedMoreInput) {
+      ASSERT_NO_FATAL_FAILURE(WriteSingleInput(start_index));
+      ++start_index;
+      --number_of_inputs_to_write;
+    } else if (event.status == kError || event.status == kTimeout) {
+      // Assume that the caller does't expect an error when |event_cb| isn't
+      // provided.
+      ASSERT_TRUE(event_cb);
+      bool continue_process = true;
+      event_cb(event, &continue_process);
+      ASSERT_FALSE(continue_process);
+      return;
+    } else {
+      ASSERT_EQ(event.status, kBufferFull);
+    }
+    if (event.frame) {
+      ASSERT_FALSE(event.frame->is_end_of_stream());
+      if (!decoded_frames_.empty()) {
+        ASSERT_LT(decoded_frames_.back()->timestamp(),
+                  event.frame->timestamp());
+      }
+      decoded_frames_.push_back(event.frame);
+      ASSERT_TRUE(AlmostEqualTime(*outstanding_inputs_.begin(),
+                                  event.frame->timestamp()));
+      outstanding_inputs_.erase(outstanding_inputs_.begin());
+    }
+    if (event_cb) {
+      bool continue_process = true;
+      event_cb(event, &continue_process);
+      if (!continue_process) {
+        return;
+      }
+    }
+  }
+}
+
+void VideoDecoderTestFixture::DrainOutputs(bool* error_occurred,
+                                           EventCB event_cb) {
+  if (error_occurred) {
+    *error_occurred = false;
+  }
+
+  bool end_of_stream_decoded = false;
+
+  while (!end_of_stream_decoded) {
+    Event event;
+    ASSERT_NO_FATAL_FAILURE(WaitForNextEvent(&event));
+    if (event.status == kError || event.status == kTimeout) {
+      if (error_occurred) {
+        *error_occurred = true;
+      } else {
+        FAIL();
+      }
+      return;
+    }
+    if (event.frame) {
+      if (event.frame->is_end_of_stream()) {
+        end_of_stream_decoded = true;
+        if (!outstanding_inputs_.empty()) {
+          SB_LOG(WARNING) << "|outstanding_inputs_| is not empty.";
+          if (error_occurred) {
+            *error_occurred = true;
+          } else {
+            // |error_occurred| is NULL indicates that the caller doesn't
+            // expect an error, use the following redundant ASSERT to trigger
+            // a failure.
+            ASSERT_TRUE(outstanding_inputs_.empty());
+          }
+        }
+      } else {
+        if (!decoded_frames_.empty()) {
+          ASSERT_LT(decoded_frames_.back()->timestamp(),
+                    event.frame->timestamp());
+        }
+        decoded_frames_.push_back(event.frame);
+        ASSERT_TRUE(AlmostEqualTime(*outstanding_inputs_.begin(),
+                                    event.frame->timestamp()));
+        outstanding_inputs_.erase(outstanding_inputs_.begin());
+      }
+    }
+    if (event_cb) {
+      bool continue_process = true;
+      event_cb(event, &continue_process);
+      if (!continue_process) {
+        return;
+      }
+    }
+  }
+}
+
+void VideoDecoderTestFixture::ResetDecoderAndClearPendingEvents() {
+  video_decoder_->Reset();
+  ScopedLock scoped_lock(mutex_);
+  event_queue_.clear();
+  need_more_input_ = true;
+  end_of_stream_written_ = false;
+  outstanding_inputs_.clear();
+  decoded_frames_.clear();
+}
+
+scoped_refptr<InputBuffer> VideoDecoderTestFixture::GetVideoInputBuffer(
+    size_t index) const {
+  auto video_sample_info =
+      dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeVideo, index);
+#if SB_API_VERSION >= 11
+  auto input_buffer =
+      new InputBuffer(StubDeallocateSampleFunc, NULL, NULL, video_sample_info);
+#else   // SB_API_VERSION >= 11
+  auto input_buffer =
+      new InputBuffer(kSbMediaTypeVideo, StubDeallocateSampleFunc, NULL, NULL,
+                      video_sample_info, NULL);
+#endif  // SB_API_VERSION >= 11
+  auto iter = invalid_inputs_.find(index);
+  if (iter != invalid_inputs_.end()) {
+    std::vector<uint8_t> content(input_buffer->size(), iter->second);
+    // Replace the content with invalid data.
+    input_buffer->SetDecryptedContent(content.data(),
+                                      static_cast<int>(content.size()));
+  }
+  return input_buffer;
+}
+
+}  // namespace testing
+}  // namespace filter
+}  // namespace player
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.h b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.h
new file mode 100644
index 0000000..1ffaab3
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.h
@@ -0,0 +1,183 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_TESTING_VIDEO_DECODER_TEST_FIXTURE_H_
+#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_TESTING_VIDEO_DECODER_TEST_FIXTURE_H_
+
+#include <algorithm>
+#include <deque>
+#include <functional>
+#include <map>
+#include <set>
+
+#include "starboard/common/condition_variable.h"
+#include "starboard/common/mutex.h"
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/common/string.h"
+#include "starboard/configuration_constants.h"
+#include "starboard/drm.h"
+#include "starboard/media.h"
+#include "starboard/memory.h"
+#include "starboard/shared/starboard/media/media_util.h"
+#include "starboard/shared/starboard/player/filter/stub_player_components_factory.h"
+#include "starboard/shared/starboard/player/filter/testing/test_util.h"
+#include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
+#include "starboard/shared/starboard/player/job_queue.h"
+#include "starboard/shared/starboard/player/video_dmp_reader.h"
+#include "starboard/testing/fake_graphics_context_provider.h"
+#include "starboard/thread.h"
+#include "starboard/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// This has to be defined in the global namespace as its instance will be used
+// as SbPlayer.
+struct SbPlayerPrivate {};
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+namespace testing {
+
+class VideoDecoderTestFixture {
+ public:
+  static const SbTimeMonotonic kDefaultWaitForNextEventTimeOut =
+      5 * kSbTimeSecond;
+
+  enum Status {
+    kNeedMoreInput = VideoDecoder::kNeedMoreInput,
+    kBufferFull = VideoDecoder::kBufferFull,
+    kError,
+    kTimeout
+  };
+
+  struct Event {
+    Status status;
+    scoped_refptr<VideoFrame> frame;
+
+    Event() : status(kNeedMoreInput) {}
+    Event(Status status, scoped_refptr<VideoFrame> frame)
+        : status(status), frame(frame) {}
+  };
+
+  // This function is called inside WriteMultipleInputs() whenever an event has
+  // been processed.
+  // |continue_process| will always be a valid pointer and always contains
+  // |true| when calling this callback.  The callback can set it to false to
+  // stop further processing.
+  typedef std::function<void(const Event&, bool* continue_process)> EventCB;
+
+  VideoDecoderTestFixture(JobQueue* job_queue,
+                          ::starboard::testing::FakeGraphicsContextProvider*
+                              fake_graphics_context_provider,
+                          const char* test_filename,
+                          SbPlayerOutputMode output_mode,
+                          bool using_stub_decoder);
+
+  ~VideoDecoderTestFixture() { video_decoder_->Reset(); }
+
+  void Initialize();
+
+  void Render(VideoRendererSink::DrawFrameCB draw_frame_cb) {}
+
+  void OnDecoderStatusUpdate(VideoDecoder::Status status,
+                             const scoped_refptr<VideoFrame>& frame);
+
+  void OnError();
+
+#if SB_HAS(GLES2)
+  void AssertInvalidDecodeTarget();
+#endif  // SB_HAS(GLES2)
+
+  void WaitForNextEvent(
+      Event* event,
+      SbTimeMonotonic timeout = kDefaultWaitForNextEventTimeOut);
+
+  bool HasPendingEvents();
+
+  void GetDecodeTargetWhenSupported();
+
+  void AssertValidDecodeTargetWhenSupported();
+
+  // This has to be called when the decoder is just initialized/reseted or when
+  // status is |kNeedMoreInput|.
+  void WriteSingleInput(size_t index);
+
+  void WriteEndOfStream();
+
+  void WriteMultipleInputs(size_t start_index,
+                           size_t number_of_inputs_to_write,
+                           EventCB event_cb = EventCB());
+
+  void DrainOutputs(bool* error_occurred = NULL, EventCB event_cb = EventCB());
+
+  void ResetDecoderAndClearPendingEvents();
+
+  scoped_refptr<InputBuffer> GetVideoInputBuffer(size_t index) const;
+
+  void UseInvalidDataForInput(size_t index, uint8_t byte_to_fill) {
+    invalid_inputs_[index] = byte_to_fill;
+  }
+  const scoped_ptr<VideoDecoder>& video_decoder() const {
+    return video_decoder_;
+  }
+  const video_dmp::VideoDmpReader& dmp_reader() const { return dmp_reader_; }
+  SbPlayerOutputMode output_mode() const { return output_mode_; }
+  size_t GetDecodedFramesCount() const { return decoded_frames_.size(); }
+  void PopDecodedFrame() { decoded_frames_.pop_front(); }
+  void ClearDecodedFrames() { decoded_frames_.clear(); }
+
+ protected:
+  JobQueue* job_queue_;
+
+  Mutex mutex_;
+  std::deque<Event> event_queue_;
+
+  // Test parameter filename for the VideoDmpReader to load and test with.
+  const char* test_filename_;
+
+  // Test parameter for OutputMode.
+  SbPlayerOutputMode output_mode_;
+
+  // Test parameter for whether or not to use the StubVideoDecoder, or the
+  // platform-specific VideoDecoderImpl.
+  bool using_stub_decoder_;
+
+  ::starboard::testing::FakeGraphicsContextProvider*
+      fake_graphics_context_provider_;
+  video_dmp::VideoDmpReader dmp_reader_;
+  scoped_ptr<VideoDecoder> video_decoder_;
+
+  bool need_more_input_ = true;
+  std::set<SbTime> outstanding_inputs_;
+  std::deque<scoped_refptr<VideoFrame>> decoded_frames_;
+
+  SbPlayerPrivate player_;
+  scoped_ptr<VideoRenderAlgorithm> video_render_algorithm_;
+  scoped_refptr<VideoRendererSink> video_renderer_sink_;
+
+  bool end_of_stream_written_ = false;
+
+  std::map<size_t, uint8_t> invalid_inputs_;
+};
+
+}  // namespace testing
+}  // namespace filter
+}  // namespace player
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_TESTING_VIDEO_DECODER_TEST_FIXTURE_H_
diff --git a/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc b/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc
index 36cfe40..25302de 100644
--- a/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc
+++ b/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc
@@ -74,9 +74,6 @@
 static void DeallocateSampleFunc(SbPlayer player,
                                  void* context,
                                  const void* sample_buffer) {
-  SB_UNREFERENCED_PARAMETER(player);
-  SB_UNREFERENCED_PARAMETER(context);
-  SB_UNREFERENCED_PARAMETER(sample_buffer);
 }
 
 starboard::scoped_refptr<InputBuffer> GetAudioInputBuffer(size_t index) {
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.cc b/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.cc
index 14b442c..6573840 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.cc
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.cc
@@ -140,11 +140,9 @@
     return;
   }
   end_of_stream_written_.store(true);
-  if (!first_input_written_ && !ended_cb_called_.load()) {
-    ended_cb_called_.store(true);
-    Schedule(ended_cb_);
+  if (!first_input_written_) {
+    first_input_written_ = true;
   }
-  first_input_written_ = true;
   decoder_->WriteEndOfStream();
 }
 
@@ -162,6 +160,7 @@
   seeking_to_time_ = std::max<SbTime>(seek_to_time, 0);
   seeking_.store(true);
   end_of_stream_written_.store(false);
+  end_of_stream_decoded_.store(false);
   ended_cb_called_.store(false);
   need_more_input_.store(true);
 
@@ -181,7 +180,6 @@
 
 #if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
   buffering_state_ = kWaitForBuffer;
-  end_of_stream_decoded_.store(false);
 #endif  // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
 
   algorithm_->Reset();  // This is also guarded by sink_frames_mutex_.
@@ -254,9 +252,6 @@
   if (frame) {
 #if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
     last_output_ = SbTimeGetMonotonicNow();
-    if (frame->is_end_of_stream()) {
-      end_of_stream_decoded_.store(true);
-    }
 #endif  // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
 
     SB_DCHECK(first_input_written_);
@@ -266,6 +261,7 @@
       if (seeking_.exchange(false)) {
         Schedule(prerolled_cb_);
       }
+      end_of_stream_decoded_.store(true);
     } else if (seeking_.load() && frame->timestamp() < seeking_to_time_) {
       frame_too_early = true;
     }
@@ -339,7 +335,7 @@
   algorithm_->Render(media_time_provider_, &sink_frames_, draw_frame_cb);
   number_of_frames_.fetch_sub(
       static_cast<int32_t>(number_of_sink_frames - sink_frames_.size()));
-  if (number_of_frames_.load() <= 1 && end_of_stream_written_.load() &&
+  if (number_of_frames_.load() <= 1 && end_of_stream_decoded_.load() &&
       !ended_cb_called_.load()) {
     ended_cb_called_.store(true);
     Schedule(ended_cb_);
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.h b/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.h
index d8c0648..ee8bad0 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.h
@@ -100,6 +100,7 @@
   // and can thus avoid doing a full reset.
   bool first_input_written_ = false;
   atomic_bool end_of_stream_written_;
+  atomic_bool end_of_stream_decoded_;
   atomic_bool ended_cb_called_;
 
   atomic_bool need_more_input_;
@@ -142,7 +143,6 @@
   volatile SbTimeMonotonic last_buffering_state_update_ = 0;
   volatile SbTimeMonotonic last_output_ = 0;
   mutable volatile SbTime last_can_accept_more_data = 0;
-  atomic_bool end_of_stream_decoded_;
 
   SbTimeMonotonic time_of_last_lag_warning_;
 
diff --git a/src/starboard/shared/starboard/player/player_create.cc b/src/starboard/shared/starboard/player/player_create.cc
index e34b530..ff88e31 100644
--- a/src/starboard/shared/starboard/player/player_create.cc
+++ b/src/starboard/shared/starboard/player/player_create.cc
@@ -107,9 +107,7 @@
                         SbDecodeTargetGraphicsContextProvider* provider) {
 #endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 
-  SB_UNREFERENCED_PARAMETER(window);
 #if SB_API_VERSION >= 11
-  SB_UNREFERENCED_PARAMETER(max_video_capabilities);
 #endif  // SB_API_VERSION >= 11
 #if SB_API_VERSION >= 11
   if (audio_sample_info) {
@@ -126,9 +124,9 @@
   const int64_t kDefaultBitRate = 0;
   if (audio_codec != kSbMediaAudioCodecNone &&
       !SbMediaIsAudioSupported(audio_codec,
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
                                audio_mime,
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
                                kDefaultBitRate)) {
     SB_LOG(ERROR) << "Unsupported audio codec " << audio_codec;
     return kSbPlayerInvalid;
@@ -143,9 +141,9 @@
   if (video_codec != kSbMediaVideoCodecNone &&
       !SbMediaIsVideoSupported(
           video_codec,
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_API_VERSION >= 12
           video_mime,
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#endif  // SB_API_VERSION >= 12
 #if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
           kDefaultProfile, kDefaultLevel, kDefaultColorDepth,
           kSbMediaPrimaryIdUnspecified, kSbMediaTransferIdUnspecified,
diff --git a/src/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc b/src/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc
index f704486..3fc8e74 100644
--- a/src/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc
+++ b/src/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/player.h"
 
-int SbPlayerGetMaximumNumberOfSamplesPerWrite(SbPlayer /*player*/,
-                                              SbMediaType /*sample_type*/) {
+int SbPlayerGetMaximumNumberOfSamplesPerWrite(SbPlayer player,
+                                              SbMediaType sample_type) {
   return 1;
 }
diff --git a/src/starboard/shared/starboard/player/player_internal.h b/src/starboard/shared/starboard/player/player_internal.h
index da69e23..4a94236 100644
--- a/src/starboard/shared/starboard/player/player_internal.h
+++ b/src/starboard/shared/starboard/player/player_internal.h
@@ -76,6 +76,9 @@
       void* context,
       starboard::scoped_ptr<PlayerWorker::Handler> player_worker_handler);
 
+  SbPlayerPrivate(const SbPlayerPrivate&) = delete;
+  SbPlayerPrivate& operator=(const SbPlayerPrivate&) = delete;
+
   void UpdateMediaInfo(SbTime media_time,
                        int dropped_video_frames,
                        int ticket,
diff --git a/src/starboard/shared/starboard/player/player_worker.cc b/src/starboard/shared/starboard/player/player_worker.cc
index 07a3f8e..c4f3110 100644
--- a/src/starboard/shared/starboard/player/player_worker.cc
+++ b/src/starboard/shared/starboard/player/player_worker.cc
@@ -160,7 +160,7 @@
 void PlayerWorker::UpdatePlayerError(SbPlayerError error,
                                      const std::string& error_message) {
   error_occurred_ = true;
-  SB_LOG(WARNING) << "Encountered player error: " << error
+  SB_LOG(WARNING) << "Encountered player error " << error
                   << " with message: " << error_message;
 
   if (!player_error_func_) {
@@ -208,7 +208,7 @@
   } else {
     UpdatePlayerError(
         kSbPlayerErrorDecode,
-        "Failed to initialize PlayerWorker with error " + error_message);
+        "Failed to initialize PlayerWorker with error: " + error_message);
   }
 }
 
diff --git a/src/starboard/shared/starboard/player/player_worker.h b/src/starboard/shared/starboard/player/player_worker.h
index 936756e..6c70552 100644
--- a/src/starboard/shared/starboard/player/player_worker.h
+++ b/src/starboard/shared/starboard/player/player_worker.h
@@ -68,6 +68,8 @@
     typedef std::function<void(SbPlayerError error,
                                const std::string& error_message)>
         UpdatePlayerErrorCB;
+
+    Handler() = default;
     virtual ~Handler() {}
 
     // All the following functions return false to signal a fatal error.  The
@@ -94,6 +96,10 @@
     virtual void Stop() = 0;
 
     virtual SbDecodeTarget GetCurrentDecodeTarget() = 0;
+
+   private:
+    Handler(const Handler&) = delete;
+    Handler& operator=(const Handler&) = delete;
   };
 
   static PlayerWorker* CreateInstance(
@@ -168,6 +174,9 @@
                SbPlayer player,
                void* context);
 
+  PlayerWorker(const PlayerWorker&) = delete;
+  PlayerWorker& operator=(const PlayerWorker&) = delete;
+
   void UpdateMediaInfo(SbTime time, int dropped_video_frames, bool underflow);
 
   SbPlayerState player_state() const { return player_state_; }
diff --git a/src/starboard/shared/starboard/player/video_dmp_reader.cc b/src/starboard/shared/starboard/player/video_dmp_reader.cc
index e8d3306..8a9a96a 100644
--- a/src/starboard/shared/starboard/player/video_dmp_reader.cc
+++ b/src/starboard/shared/starboard/player/video_dmp_reader.cc
@@ -54,9 +54,6 @@
 static void DeallocateSampleFunc(SbPlayer player,
                                  void* context,
                                  const void* sample_buffer) {
-  SB_UNREFERENCED_PARAMETER(player);
-  SB_UNREFERENCED_PARAMETER(context);
-  SB_UNREFERENCED_PARAMETER(sample_buffer);
 }
 
 SbPlayerSampleInfo ConvertToPlayerSampleInfo(
diff --git a/src/starboard/shared/starboard/player/video_dmp_writer.cc b/src/starboard/shared/starboard/player/video_dmp_writer.cc
index 22c89f4..9e2a884 100644
--- a/src/starboard/shared/starboard/player/video_dmp_writer.cc
+++ b/src/starboard/shared/starboard/player/video_dmp_writer.cc
@@ -103,7 +103,6 @@
     SbDrmSystem drm_system,
     const SbMediaAudioSampleInfo* audio_sample_info) {
   // TODO: Allow dump of drm initialization data
-  SB_UNREFERENCED_PARAMETER(drm_system);
 
   PlayerToWriterMap* map = GetOrCreatePlayerToWriterMap();
   if (!map->dump_video_data()) {
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_cancel.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_cancel.cc
index 7ac0882..6b28a0d 100644
--- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_cancel.cc
+++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_cancel.cc
@@ -14,8 +14,7 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 #include "starboard/common/log.h"
 #include "starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h"
@@ -26,6 +25,6 @@
   }
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_create.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_create.cc
index 3127fa4..ae9d89a 100644
--- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_create.cc
+++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_create.cc
@@ -14,8 +14,7 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 #include "starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h"
 
@@ -24,6 +23,6 @@
   return SbSpeechRecognizerPrivate::CreateSpeechRecognizer(handler);
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_destroy.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_destroy.cc
index 1a46ae5..2aa12cc 100644
--- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_destroy.cc
+++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_destroy.cc
@@ -14,8 +14,7 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 #include "starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h"
 
@@ -25,6 +24,6 @@
   }
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h
index 9f5779a..fda5a28 100644
--- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h
+++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h
@@ -18,8 +18,7 @@
 #include "starboard/shared/internal_only.h"
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 struct SbSpeechRecognizerPrivate {
   virtual ~SbSpeechRecognizerPrivate() {}
   virtual bool Start(const SbSpeechConfiguration* configuration) = 0;
@@ -29,7 +28,7 @@
       const SbSpeechRecognizerHandler* handler);
   static void DestroySpeechRecognizer(SbSpeechRecognizer speech_recognizer);
 };
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
 
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_is_supported.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_is_supported.cc
index 102a7c0..03cd6ab 100644
--- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_is_supported.cc
+++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_is_supported.cc
@@ -14,10 +14,10 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbSpeechRecognizerIsSupported() {
   return true;
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_start.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_start.cc
index 01253a1..20e05be 100644
--- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_start.cc
+++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_start.cc
@@ -14,8 +14,7 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 #include "starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h"
 
@@ -26,6 +25,6 @@
              : false;
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_stop.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_stop.cc
index f50e53a..9c820bf 100644
--- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_stop.cc
+++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_stop.cc
@@ -14,8 +14,7 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 #include "starboard/common/log.h"
 #include "starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h"
@@ -26,6 +25,6 @@
   }
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/starboard/system_request_blur.cc b/src/starboard/shared/starboard/system_request_blur.cc
new file mode 100644
index 0000000..a2fe101
--- /dev/null
+++ b/src/starboard/shared/starboard/system_request_blur.cc
@@ -0,0 +1,25 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "starboard/shared/starboard/application.h"
+
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void SbSystemRequestBlur() {
+  starboard::shared::starboard::Application::Get()->Blur(NULL, NULL);
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/starboard/system_request_conceal.cc b/src/starboard/shared/starboard/system_request_conceal.cc
new file mode 100644
index 0000000..0208148
--- /dev/null
+++ b/src/starboard/shared/starboard/system_request_conceal.cc
@@ -0,0 +1,25 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "starboard/shared/starboard/application.h"
+
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void SbSystemRequestConceal() {
+  starboard::shared::starboard::Application::Get()->Conceal(NULL, NULL);
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/starboard/system_request_focus.cc b/src/starboard/shared/starboard/system_request_focus.cc
new file mode 100644
index 0000000..8cd34c0
--- /dev/null
+++ b/src/starboard/shared/starboard/system_request_focus.cc
@@ -0,0 +1,25 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "starboard/shared/starboard/application.h"
+
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void SbSystemRequestFocus() {
+  starboard::shared::starboard::Application::Get()->Focus(NULL, NULL);
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/starboard/system_request_freeze.cc b/src/starboard/shared/starboard/system_request_freeze.cc
new file mode 100644
index 0000000..4ce9bed
--- /dev/null
+++ b/src/starboard/shared/starboard/system_request_freeze.cc
@@ -0,0 +1,25 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "starboard/shared/starboard/application.h"
+
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void SbSystemRequestFreeze() {
+  starboard::shared::starboard::Application::Get()->Freeze(NULL, NULL);
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/starboard/system_request_pause.cc b/src/starboard/shared/starboard/system_request_pause.cc
index c5650a5..923201e 100644
--- a/src/starboard/shared/starboard/system_request_pause.cc
+++ b/src/starboard/shared/starboard/system_request_pause.cc
@@ -16,6 +16,10 @@
 
 #include "starboard/shared/starboard/application.h"
 
+#if SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION && \
+    !SB_HAS(CONCEALED_STATE)
 void SbSystemRequestPause() {
   starboard::shared::starboard::Application::Get()->Pause(NULL, NULL);
 }
+#endif  // SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION &&
+        // !SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/starboard/system_request_reveal.cc b/src/starboard/shared/starboard/system_request_reveal.cc
new file mode 100644
index 0000000..eca0af0
--- /dev/null
+++ b/src/starboard/shared/starboard/system_request_reveal.cc
@@ -0,0 +1,25 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "starboard/shared/starboard/application.h"
+
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void SbSystemRequestReveal() {
+  starboard::shared::starboard::Application::Get()->Reveal(NULL, NULL);
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/starboard/system_request_suspend.cc b/src/starboard/shared/starboard/system_request_suspend.cc
index 9b05a68..ee7ef8f 100644
--- a/src/starboard/shared/starboard/system_request_suspend.cc
+++ b/src/starboard/shared/starboard/system_request_suspend.cc
@@ -16,6 +16,10 @@
 
 #include "starboard/shared/starboard/application.h"
 
+#if SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION && \
+    !SB_HAS(CONCEALED_STATE)
 void SbSystemRequestSuspend() {
   starboard::shared::starboard::Application::Get()->Suspend(NULL, NULL);
 }
+#endif  // SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION &&
+        // !SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/starboard/system_request_unpause.cc b/src/starboard/shared/starboard/system_request_unpause.cc
index 230b884..542cabe 100644
--- a/src/starboard/shared/starboard/system_request_unpause.cc
+++ b/src/starboard/shared/starboard/system_request_unpause.cc
@@ -16,6 +16,10 @@
 
 #include "starboard/shared/starboard/application.h"
 
+#if SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION && \
+    !SB_HAS(CONCEALED_STATE)
 void SbSystemRequestUnpause() {
   starboard::shared::starboard::Application::Get()->Unpause(NULL, NULL);
 }
+#endif  // SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION &&
+        // !SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/starboard/thread_checker.h b/src/starboard/shared/starboard/thread_checker.h
index b19b1d5..412b9ee 100644
--- a/src/starboard/shared/starboard/thread_checker.h
+++ b/src/starboard/shared/starboard/thread_checker.h
@@ -29,7 +29,6 @@
   enum Type { kSetThreadIdOnCreation, kSetThreadIdOnFirstCheck };
 
   explicit ThreadChecker(Type type = kSetThreadIdOnCreation) {
-    SB_UNREFERENCED_PARAMETER(type);
   }
 
   void Detach() {}
diff --git a/src/starboard/shared/starboard/thread_local_storage_internal.cc b/src/starboard/shared/starboard/thread_local_storage_internal.cc
index f98994b..a22a4b3 100644
--- a/src/starboard/shared/starboard/thread_local_storage_internal.cc
+++ b/src/starboard/shared/starboard/thread_local_storage_internal.cc
@@ -229,12 +229,12 @@
   KeyRecord* record = &data_->key_table_[key->index];
 
   record->destructor = destructor;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
   SbMemorySet(record->values.data(), 0,
               record->values.size() * sizeof(record->values[0]));
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else   // SB_API_VERSION >= 12
   SbMemorySet(record->values, 0, sizeof(record->values));
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
   record->valid = true;
 
   return key;
diff --git a/src/starboard/shared/starboard/thread_local_storage_internal.h b/src/starboard/shared/starboard/thread_local_storage_internal.h
index 41f8fce..4e322f4 100644
--- a/src/starboard/shared/starboard/thread_local_storage_internal.h
+++ b/src/starboard/shared/starboard/thread_local_storage_internal.h
@@ -58,11 +58,11 @@
   struct KeyRecord {
     bool valid;
     SbThreadLocalDestructor destructor;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
     std::vector<void*> values(kMaxThreads);
-#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#else   // SB_API_VERSION >= 12
     void* values[kMaxThreads];
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
   };
 
   // Sets up the specified key.
diff --git a/src/starboard/shared/stub/accessibility_get_caption_settings.cc b/src/starboard/shared/stub/accessibility_get_caption_settings.cc
index 2f042d7..382b3ab 100644
--- a/src/starboard/shared/stub/accessibility_get_caption_settings.cc
+++ b/src/starboard/shared/stub/accessibility_get_caption_settings.cc
@@ -17,9 +17,17 @@
 #include "starboard/accessibility.h"
 #include "starboard/memory.h"
 
-#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+#if SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
 bool SbAccessibilityGetCaptionSettings(
     SbAccessibilityCaptionSettings* caption_settings) {
-  return false;
+  if (!caption_settings ||
+      !SbMemoryIsZero(caption_settings,
+                      sizeof(SbAccessibilityCaptionSettings))) {
+    return false;
+  }
+
+  // Since kSbAccessibilityCaptionStateUnsupported == 0, there is no need to
+  // explicitly set states to kSbAccessibilityCaptionStateUnsupported.
+  return true;
 }
-#endif  // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
diff --git a/src/starboard/shared/stub/accessibility_set_captions_enabled.cc b/src/starboard/shared/stub/accessibility_set_captions_enabled.cc
index 29e910c..0665fd5 100644
--- a/src/starboard/shared/stub/accessibility_set_captions_enabled.cc
+++ b/src/starboard/shared/stub/accessibility_set_captions_enabled.cc
@@ -15,9 +15,8 @@
 #include "starboard/accessibility.h"
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+#if SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
 bool SbAccessibilitySetCaptionsEnabled(bool enabled) {
-  SB_UNREFERENCED_PARAMETER(enabled);
   return false;
 }
-#endif  // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+#endif  // SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
diff --git a/src/starboard/shared/stub/atomic_public.h b/src/starboard/shared/stub/atomic_public.h
index 68b5857..6aa6f89 100644
--- a/src/starboard/shared/stub/atomic_public.h
+++ b/src/starboard/shared/stub/atomic_public.h
@@ -25,30 +25,21 @@
 SbAtomicNoBarrier_CompareAndSwap(volatile SbAtomic32* ptr,
                                  SbAtomic32 old_value,
                                  SbAtomic32 new_value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(old_value);
-  SB_UNREFERENCED_PARAMETER(new_value);
   return 0;
 }
 
 SB_C_FORCE_INLINE SbAtomic32
 SbAtomicNoBarrier_Exchange(volatile SbAtomic32* ptr, SbAtomic32 new_value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(new_value);
   return 0;
 }
 
 SB_C_FORCE_INLINE SbAtomic32
 SbAtomicNoBarrier_Increment(volatile SbAtomic32* ptr, SbAtomic32 increment) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(increment);
   return 0;
 }
 
 SB_C_FORCE_INLINE SbAtomic32 SbAtomicBarrier_Increment(volatile SbAtomic32* ptr,
                                                        SbAtomic32 increment) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(increment);
   return 0;
 }
 
@@ -56,9 +47,6 @@
 SbAtomicAcquire_CompareAndSwap(volatile SbAtomic32* ptr,
                                SbAtomic32 old_value,
                                SbAtomic32 new_value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(old_value);
-  SB_UNREFERENCED_PARAMETER(new_value);
   return 0;
 }
 
@@ -66,9 +54,6 @@
 SbAtomicRelease_CompareAndSwap(volatile SbAtomic32* ptr,
                                SbAtomic32 old_value,
                                SbAtomic32 new_value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(old_value);
-  SB_UNREFERENCED_PARAMETER(new_value);
   return 0;
 }
 
@@ -76,37 +61,28 @@
 
 SB_C_FORCE_INLINE void SbAtomicNoBarrier_Store(volatile SbAtomic32* ptr,
                                                SbAtomic32 value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(value);
 }
 
 SB_C_FORCE_INLINE void SbAtomicAcquire_Store(volatile SbAtomic32* ptr,
                                              SbAtomic32 value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(value);
 }
 
 SB_C_FORCE_INLINE void SbAtomicRelease_Store(volatile SbAtomic32* ptr,
                                              SbAtomic32 value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(value);
 }
 
 SB_C_FORCE_INLINE SbAtomic32
 SbAtomicNoBarrier_Load(volatile const SbAtomic32* ptr) {
-  SB_UNREFERENCED_PARAMETER(ptr);
   return 0;
 }
 
 SB_C_FORCE_INLINE SbAtomic32
 SbAtomicAcquire_Load(volatile const SbAtomic32* ptr) {
-  SB_UNREFERENCED_PARAMETER(ptr);
   return 0;
 }
 
 SB_C_FORCE_INLINE SbAtomic32
 SbAtomicRelease_Load(volatile const SbAtomic32* ptr) {
-  SB_UNREFERENCED_PARAMETER(ptr);
   return 0;
 }
 
@@ -114,21 +90,15 @@
 SbAtomicRelease_CompareAndSwap8(volatile SbAtomic8* ptr,
                                SbAtomic8 old_value,
                                SbAtomic8 new_value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(old_value);
-  SB_UNREFERENCED_PARAMETER(new_value);
   return 0;
 }
 
 SB_C_FORCE_INLINE void
 SbAtomicNoBarrier_Store8(volatile SbAtomic8* ptr, SbAtomic8 value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(value);
 }
 
 SB_C_FORCE_INLINE SbAtomic8
 SbAtomicNoBarrier_Load8(volatile const SbAtomic8* ptr) {
-  SB_UNREFERENCED_PARAMETER(ptr);
   return 0;
 }
 
@@ -138,30 +108,21 @@
 SbAtomicNoBarrier_CompareAndSwap64(volatile SbAtomic64* ptr,
                                    SbAtomic64 old_value,
                                    SbAtomic64 new_value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(old_value);
-  SB_UNREFERENCED_PARAMETER(new_value);
   return 0;
 }
 
 SB_C_FORCE_INLINE SbAtomic64
 SbAtomicNoBarrier_Exchange64(volatile SbAtomic64* ptr, SbAtomic64 new_value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(new_value);
   return 0;
 }
 
 SB_C_FORCE_INLINE SbAtomic64
 SbAtomicNoBarrier_Increment64(volatile SbAtomic64* ptr, SbAtomic64 increment) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(increment);
   return 0;
 }
 
 SB_C_FORCE_INLINE SbAtomic64
 SbAtomicBarrier_Increment64(volatile SbAtomic64* ptr, SbAtomic64 increment) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(increment);
   return 0;
 }
 
@@ -169,9 +130,6 @@
 SbAtomicAcquire_CompareAndSwap64(volatile SbAtomic64* ptr,
                                  SbAtomic64 old_value,
                                  SbAtomic64 new_value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(old_value);
-  SB_UNREFERENCED_PARAMETER(new_value);
   return 0;
 }
 
@@ -179,45 +137,33 @@
 SbAtomicRelease_CompareAndSwap64(volatile SbAtomic64* ptr,
                                  SbAtomic64 old_value,
                                  SbAtomic64 new_value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(old_value);
-  SB_UNREFERENCED_PARAMETER(new_value);
   return 0;
 }
 
 SB_C_FORCE_INLINE void SbAtomicNoBarrier_Store64(volatile SbAtomic64* ptr,
                                                  SbAtomic64 value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(value);
 }
 
 SB_C_FORCE_INLINE void SbAtomicAcquire_Store64(volatile SbAtomic64* ptr,
                                                SbAtomic64 value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(value);
 }
 
 SB_C_FORCE_INLINE void SbAtomicRelease_Store64(volatile SbAtomic64* ptr,
                                                SbAtomic64 value) {
-  SB_UNREFERENCED_PARAMETER(ptr);
-  SB_UNREFERENCED_PARAMETER(value);
 }
 
 SB_C_FORCE_INLINE SbAtomic64
 SbAtomicNoBarrier_Load64(volatile const SbAtomic64* ptr) {
-  SB_UNREFERENCED_PARAMETER(ptr);
   return 0;
 }
 
 SB_C_FORCE_INLINE SbAtomic64
 SbAtomicAcquire_Load64(volatile const SbAtomic64* ptr) {
-  SB_UNREFERENCED_PARAMETER(ptr);
   return 0;
 }
 
 SB_C_FORCE_INLINE SbAtomic64
 SbAtomicRelease_Load64(volatile const SbAtomic64* ptr) {
-  SB_UNREFERENCED_PARAMETER(ptr);
   return 0;
 }
 #endif  // SB_HAS(64_BIT_ATOMICS)
diff --git a/src/starboard/shared/stub/audio_sink_destroy.cc b/src/starboard/shared/stub/audio_sink_destroy.cc
index a9d5a2b..54287d4 100644
--- a/src/starboard/shared/stub/audio_sink_destroy.cc
+++ b/src/starboard/shared/stub/audio_sink_destroy.cc
@@ -14,4 +14,4 @@
 
 #include "starboard/audio_sink.h"
 
-void SbAudioSinkDestroy(SbAudioSink /*audio_sink*/) {}
+void SbAudioSinkDestroy(SbAudioSink audio_sink) {}
diff --git a/src/starboard/shared/stub/audio_sink_get_min_buffer_size_in_frames.cc b/src/starboard/shared/stub/audio_sink_get_min_buffer_size_in_frames.cc
index f64f8ec..9768991 100644
--- a/src/starboard/shared/stub/audio_sink_get_min_buffer_size_in_frames.cc
+++ b/src/starboard/shared/stub/audio_sink_get_min_buffer_size_in_frames.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/audio_sink.h"
 
-int SbAudioSinkGetMinBufferSizeInFrames(int /*channels*/,
-                                        SbMediaAudioSampleType /*sample_type*/,
-                                        int /*sampling_frequency_hz*/) {
-  return 8 * 1024;
+int SbAudioSinkGetMinBufferSizeInFrames(int channels,
+                                        SbMediaAudioSampleType sample_type,
+                                        int sampling_frequency_hz) {
+  return 5 * 1024;
 }
diff --git a/src/starboard/shared/stub/audio_sink_is_valid.cc b/src/starboard/shared/stub/audio_sink_is_valid.cc
index fb4848a..1efc597 100644
--- a/src/starboard/shared/stub/audio_sink_is_valid.cc
+++ b/src/starboard/shared/stub/audio_sink_is_valid.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/audio_sink.h"
 
-bool SbAudioSinkIsValid(SbAudioSink /*audio_sink*/) {
+bool SbAudioSinkIsValid(SbAudioSink audio_sink) {
   return true;
 }
diff --git a/src/starboard/shared/stub/byte_swap.cc b/src/starboard/shared/stub/byte_swap.cc
index e8b1874..58ec716 100644
--- a/src/starboard/shared/stub/byte_swap.cc
+++ b/src/starboard/shared/stub/byte_swap.cc
@@ -17,14 +17,26 @@
 
 #include "starboard/common/byte_swap.h"
 
-int16_t SbByteSwapS16(int16_t /*value*/) { return 0; }
+int16_t SbByteSwapS16(int16_t value) {
+  return 0;
+}
 
-uint16_t SbByteSwapU16(uint16_t /*value*/) { return 0; }
+uint16_t SbByteSwapU16(uint16_t value) {
+  return 0;
+}
 
-int32_t SbByteSwapS32(int32_t /*value*/) { return 0; }
+int32_t SbByteSwapS32(int32_t value) {
+  return 0;
+}
 
-uint32_t SbByteSwapU32(uint32_t /*value*/) { return 0; }
+uint32_t SbByteSwapU32(uint32_t value) {
+  return 0;
+}
 
-int64_t SbByteSwapS64(int64_t /*value*/) { return 0; }
+int64_t SbByteSwapS64(int64_t value) {
+  return 0;
+}
 
-uint64_t SbByteSwapU64(uint64_t /*value*/) { return 0; }
+uint64_t SbByteSwapU64(uint64_t value) {
+  return 0;
+}
diff --git a/src/starboard/shared/stub/character_is_alphanumeric.cc b/src/starboard/shared/stub/character_is_alphanumeric.cc
index 470c631..8a6b2b7 100644
--- a/src/starboard/shared/stub/character_is_alphanumeric.cc
+++ b/src/starboard/shared/stub/character_is_alphanumeric.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/character.h"
 
-bool SbCharacterIsAlphanumeric(int /*c*/) {
+bool SbCharacterIsAlphanumeric(int c) {
   return false;
 }
diff --git a/src/starboard/shared/stub/character_is_digit.cc b/src/starboard/shared/stub/character_is_digit.cc
index a308ad6..4f85cb8 100644
--- a/src/starboard/shared/stub/character_is_digit.cc
+++ b/src/starboard/shared/stub/character_is_digit.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/character.h"
 
-bool SbCharacterIsDigit(int /*c*/) {
+bool SbCharacterIsDigit(int c) {
   return false;
 }
diff --git a/src/starboard/shared/stub/character_is_hex_digit.cc b/src/starboard/shared/stub/character_is_hex_digit.cc
index 4e3ae40..1fa78aa 100644
--- a/src/starboard/shared/stub/character_is_hex_digit.cc
+++ b/src/starboard/shared/stub/character_is_hex_digit.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/character.h"
 
-bool SbCharacterIsHexDigit(int /*c*/) {
+bool SbCharacterIsHexDigit(int c) {
   return false;
 }
diff --git a/src/starboard/shared/stub/character_is_space.cc b/src/starboard/shared/stub/character_is_space.cc
index d7abc8a..f5157e8 100644
--- a/src/starboard/shared/stub/character_is_space.cc
+++ b/src/starboard/shared/stub/character_is_space.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/character.h"
 
-bool SbCharacterIsSpace(int /*c*/) {
+bool SbCharacterIsSpace(int c) {
   return false;
 }
diff --git a/src/starboard/shared/stub/character_is_upper.cc b/src/starboard/shared/stub/character_is_upper.cc
index 896129c..ebecfae 100644
--- a/src/starboard/shared/stub/character_is_upper.cc
+++ b/src/starboard/shared/stub/character_is_upper.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/character.h"
 
-bool SbCharacterIsUpper(int /*c*/) {
+bool SbCharacterIsUpper(int c) {
   return false;
 }
diff --git a/src/starboard/shared/stub/condition_variable_broadcast.cc b/src/starboard/shared/stub/condition_variable_broadcast.cc
index a36065d..f7bfa45 100644
--- a/src/starboard/shared/stub/condition_variable_broadcast.cc
+++ b/src/starboard/shared/stub/condition_variable_broadcast.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/condition_variable.h"
 
-bool SbConditionVariableBroadcast(SbConditionVariable* /*condition*/) {
+bool SbConditionVariableBroadcast(SbConditionVariable* condition) {
   return false;
 }
diff --git a/src/starboard/shared/stub/condition_variable_create.cc b/src/starboard/shared/stub/condition_variable_create.cc
index 29feace..c11de47 100644
--- a/src/starboard/shared/stub/condition_variable_create.cc
+++ b/src/starboard/shared/stub/condition_variable_create.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/common/condition_variable.h"
 
-bool SbConditionVariableCreate(SbConditionVariable* /*out_condition*/,
-                               SbMutex* /*opt_mutex*/) {
+bool SbConditionVariableCreate(SbConditionVariable* out_condition,
+                               SbMutex* opt_mutex) {
   return false;
 }
diff --git a/src/starboard/shared/stub/condition_variable_destroy.cc b/src/starboard/shared/stub/condition_variable_destroy.cc
index cdd9d1d..5b213d6 100644
--- a/src/starboard/shared/stub/condition_variable_destroy.cc
+++ b/src/starboard/shared/stub/condition_variable_destroy.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/condition_variable.h"
 
-bool SbConditionVariableDestroy(SbConditionVariable* /*condition*/) {
+bool SbConditionVariableDestroy(SbConditionVariable* condition) {
   return false;
 }
diff --git a/src/starboard/shared/stub/condition_variable_signal.cc b/src/starboard/shared/stub/condition_variable_signal.cc
index 82118a5..73589d4 100644
--- a/src/starboard/shared/stub/condition_variable_signal.cc
+++ b/src/starboard/shared/stub/condition_variable_signal.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/condition_variable.h"
 
-bool SbConditionVariableSignal(SbConditionVariable* /*condition*/) {
+bool SbConditionVariableSignal(SbConditionVariable* condition) {
   return false;
 }
diff --git a/src/starboard/shared/stub/condition_variable_wait.cc b/src/starboard/shared/stub/condition_variable_wait.cc
index d73828e..e649efd 100644
--- a/src/starboard/shared/stub/condition_variable_wait.cc
+++ b/src/starboard/shared/stub/condition_variable_wait.cc
@@ -15,7 +15,7 @@
 #include "starboard/common/condition_variable.h"
 
 SbConditionVariableResult SbConditionVariableWait(
-    SbConditionVariable* /*condition*/,
-    SbMutex* /*mutex*/) {
+    SbConditionVariable* condition,
+    SbMutex* mutex) {
   return kSbConditionVariableFailed;
 }
diff --git a/src/starboard/shared/stub/condition_variable_wait_timed.cc b/src/starboard/shared/stub/condition_variable_wait_timed.cc
index ac096af..f7fcd31 100644
--- a/src/starboard/shared/stub/condition_variable_wait_timed.cc
+++ b/src/starboard/shared/stub/condition_variable_wait_timed.cc
@@ -15,8 +15,8 @@
 #include "starboard/common/condition_variable.h"
 
 SbConditionVariableResult SbConditionVariableWaitTimed(
-    SbConditionVariable* /*condition*/,
-    SbMutex* /*mutex*/,
-    SbTime /*timeout*/) {
+    SbConditionVariable* condition,
+    SbMutex* mutex,
+    SbTime timeout) {
   return kSbConditionVariableFailed;
 }
diff --git a/src/starboard/shared/stub/cryptography_create_transformer.cc b/src/starboard/shared/stub/cryptography_create_transformer.cc
index ee81941..68ff25b 100644
--- a/src/starboard/shared/stub/cryptography_create_transformer.cc
+++ b/src/starboard/shared/stub/cryptography_create_transformer.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 
@@ -27,15 +27,7 @@
     int initialization_vector_size,
     const void* key,
     int key_size) {
-  SB_UNREFERENCED_PARAMETER(algorithm);
-  SB_UNREFERENCED_PARAMETER(block_size_bits);
-  SB_UNREFERENCED_PARAMETER(direction);
-  SB_UNREFERENCED_PARAMETER(mode);
-  SB_UNREFERENCED_PARAMETER(initialization_vector);
-  SB_UNREFERENCED_PARAMETER(initialization_vector_size);
-  SB_UNREFERENCED_PARAMETER(key);
-  SB_UNREFERENCED_PARAMETER(key_size);
   return kSbCryptographyInvalidTransformer;
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/stub/cryptography_destroy_transformer.cc b/src/starboard/shared/stub/cryptography_destroy_transformer.cc
index 79680c5..497548d 100644
--- a/src/starboard/shared/stub/cryptography_destroy_transformer.cc
+++ b/src/starboard/shared/stub/cryptography_destroy_transformer.cc
@@ -14,12 +14,11 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 
 void SbCryptographyDestroyTransformer(SbCryptographyTransformer transformer) {
-  SB_UNREFERENCED_PARAMETER(transformer);
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/stub/cryptography_get_tag.cc b/src/starboard/shared/stub/cryptography_get_tag.cc
index ff75ba3..53f7066 100644
--- a/src/starboard/shared/stub/cryptography_get_tag.cc
+++ b/src/starboard/shared/stub/cryptography_get_tag.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 
@@ -22,10 +22,7 @@
     SbCryptographyTransformer transformer,
     void* out_tag,
     int out_tag_size) {
-  SB_UNREFERENCED_PARAMETER(transformer);
-  SB_UNREFERENCED_PARAMETER(out_tag);
-  SB_UNREFERENCED_PARAMETER(out_tag_size);
   return false;
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/stub/cryptography_set_authenticated_data.cc b/src/starboard/shared/stub/cryptography_set_authenticated_data.cc
index b6df57e..c5d2ea2 100644
--- a/src/starboard/shared/stub/cryptography_set_authenticated_data.cc
+++ b/src/starboard/shared/stub/cryptography_set_authenticated_data.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 
@@ -22,10 +22,7 @@
     SbCryptographyTransformer transformer,
     const void* data,
     int data_size) {
-  SB_UNREFERENCED_PARAMETER(transformer);
-  SB_UNREFERENCED_PARAMETER(data);
-  SB_UNREFERENCED_PARAMETER(data_size);
   return false;
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/stub/cryptography_set_initialization_vector.cc b/src/starboard/shared/stub/cryptography_set_initialization_vector.cc
index 94c2485..8be7f5d 100644
--- a/src/starboard/shared/stub/cryptography_set_initialization_vector.cc
+++ b/src/starboard/shared/stub/cryptography_set_initialization_vector.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 
@@ -22,9 +22,6 @@
     SbCryptographyTransformer transformer,
     const void* initialization_vector,
     int initialization_vector_size) {
-  SB_UNREFERENCED_PARAMETER(transformer);
-  SB_UNREFERENCED_PARAMETER(initialization_vector);
-  SB_UNREFERENCED_PARAMETER(initialization_vector_size);
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/stub/cryptography_transform.cc b/src/starboard/shared/stub/cryptography_transform.cc
index b6266e2..d600833 100644
--- a/src/starboard/shared/stub/cryptography_transform.cc
+++ b/src/starboard/shared/stub/cryptography_transform.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+#if SB_API_VERSION < 12
 
 #include "starboard/cryptography.h"
 
@@ -22,11 +22,7 @@
                             const void* in_data,
                             int in_data_size,
                             void* out_data) {
-  SB_UNREFERENCED_PARAMETER(transformer);
-  SB_UNREFERENCED_PARAMETER(in_data);
-  SB_UNREFERENCED_PARAMETER(in_data_size);
-  SB_UNREFERENCED_PARAMETER(out_data);
   return 0;
 }
 
-#endif  // SB_CRYPTOAPI_DEPRECATED_VERSION
+#endif  // SB_API_VERSION < 12
diff --git a/src/starboard/shared/stub/decode_target_destroy.cc b/src/starboard/shared/stub/decode_target_destroy.cc
index a6d0efe..d7d803c 100644
--- a/src/starboard/shared/stub/decode_target_destroy.cc
+++ b/src/starboard/shared/stub/decode_target_destroy.cc
@@ -14,4 +14,4 @@
 
 #include "starboard/decode_target.h"
 
-void SbDecodeTargetDestroy(SbDecodeTarget /*decode_target*/) {}
+void SbDecodeTargetDestroy(SbDecodeTarget decode_target) {}
diff --git a/src/starboard/shared/stub/decode_target_get_info.cc b/src/starboard/shared/stub/decode_target_get_info.cc
index 8b16ef3..1f7363c 100644
--- a/src/starboard/shared/stub/decode_target_get_info.cc
+++ b/src/starboard/shared/stub/decode_target_get_info.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/decode_target.h"
 
-bool SbDecodeTargetGetInfo(SbDecodeTarget /*decode_target*/,
-                           SbDecodeTargetInfo* /*out_info*/) {
+bool SbDecodeTargetGetInfo(SbDecodeTarget decode_target,
+                           SbDecodeTargetInfo* out_info) {
   return false;
 }
diff --git a/src/starboard/shared/stub/decode_target_release.cc b/src/starboard/shared/stub/decode_target_release.cc
index f928cf1..265077c 100644
--- a/src/starboard/shared/stub/decode_target_release.cc
+++ b/src/starboard/shared/stub/decode_target_release.cc
@@ -14,4 +14,4 @@
 
 #include "starboard/decode_target.h"
 
-void SbDecodeTargetRelease(SbDecodeTarget /*decode_target*/) {}
+void SbDecodeTargetRelease(SbDecodeTarget decode_target) {}
diff --git a/src/starboard/shared/stub/directory_can_open.cc b/src/starboard/shared/stub/directory_can_open.cc
index afbd00d..41ebde0 100644
--- a/src/starboard/shared/stub/directory_can_open.cc
+++ b/src/starboard/shared/stub/directory_can_open.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/directory.h"
 
-bool SbDirectoryCanOpen(const char* /*path*/) {
+bool SbDirectoryCanOpen(const char* path) {
   return false;
 }
diff --git a/src/starboard/shared/stub/directory_close.cc b/src/starboard/shared/stub/directory_close.cc
index 81c8079..4ceffe7 100644
--- a/src/starboard/shared/stub/directory_close.cc
+++ b/src/starboard/shared/stub/directory_close.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/directory.h"
 
-bool SbDirectoryClose(SbDirectory /*directory*/) {
+bool SbDirectoryClose(SbDirectory directory) {
   return false;
 }
diff --git a/src/starboard/shared/stub/directory_create.cc b/src/starboard/shared/stub/directory_create.cc
index 9d37877..25a0d08 100644
--- a/src/starboard/shared/stub/directory_create.cc
+++ b/src/starboard/shared/stub/directory_create.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/directory.h"
 
-bool SbDirectoryCreate(const char* /*path*/) {
+bool SbDirectoryCreate(const char* path) {
   return false;
 }
diff --git a/src/starboard/shared/stub/directory_get_next.cc b/src/starboard/shared/stub/directory_get_next.cc
index 8987598..01acdf8 100644
--- a/src/starboard/shared/stub/directory_get_next.cc
+++ b/src/starboard/shared/stub/directory_get_next.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/directory.h"
 
-bool SbDirectoryGetNext(SbDirectory /*directory*/,
-                        char* /*out_entry*/,
-                        size_t /* out_entry_size */) {
+bool SbDirectoryGetNext(SbDirectory directory,
+                        char* out_entry,
+                        size_t out_entry_size) {
   return false;
 }
diff --git a/src/starboard/shared/stub/directory_open.cc b/src/starboard/shared/stub/directory_open.cc
index d8ba8e6..5bd433c 100644
--- a/src/starboard/shared/stub/directory_open.cc
+++ b/src/starboard/shared/stub/directory_open.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/directory.h"
 
-SbDirectory SbDirectoryOpen(const char* /*path*/, SbFileError* /*out_error*/) {
+SbDirectory SbDirectoryOpen(const char* path, SbFileError* out_error) {
   return kSbDirectoryInvalid;
 }
diff --git a/src/starboard/shared/stub/double_absolute.cc b/src/starboard/shared/stub/double_absolute.cc
index 7f94964..a0117da 100644
--- a/src/starboard/shared/stub/double_absolute.cc
+++ b/src/starboard/shared/stub/double_absolute.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/double.h"
 
-double SbDoubleAbsolute(double /*d*/) {
+double SbDoubleAbsolute(double d) {
   return 0.0;
 }
diff --git a/src/starboard/shared/stub/double_exponent.cc b/src/starboard/shared/stub/double_exponent.cc
index 0ee74a3..c79cd28 100644
--- a/src/starboard/shared/stub/double_exponent.cc
+++ b/src/starboard/shared/stub/double_exponent.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/double.h"
 
-double SbDoubleExponent(const double /*base*/, const double /*exponent*/) {
+double SbDoubleExponent(const double base, const double exponent) {
   return 0.0;
 }
diff --git a/src/starboard/shared/stub/double_floor.cc b/src/starboard/shared/stub/double_floor.cc
index bbc3775..4d83750 100644
--- a/src/starboard/shared/stub/double_floor.cc
+++ b/src/starboard/shared/stub/double_floor.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/double.h"
 
-double SbDoubleFloor(double /*d*/) {
+double SbDoubleFloor(double d) {
   return 0.0;
 }
diff --git a/src/starboard/shared/stub/double_is_finite.cc b/src/starboard/shared/stub/double_is_finite.cc
index 4473ae8..7636706 100644
--- a/src/starboard/shared/stub/double_is_finite.cc
+++ b/src/starboard/shared/stub/double_is_finite.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/double.h"
 
-bool SbDoubleIsFinite(const double /*d*/) {
+bool SbDoubleIsFinite(const double d) {
   return false;
 }
diff --git a/src/starboard/shared/stub/double_is_nan.cc b/src/starboard/shared/stub/double_is_nan.cc
index 96d4e0d..4b0fdef 100644
--- a/src/starboard/shared/stub/double_is_nan.cc
+++ b/src/starboard/shared/stub/double_is_nan.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/double.h"
 
-bool SbDoubleIsNan(const double /*d*/) {
+bool SbDoubleIsNan(const double d) {
   return false;
 }
diff --git a/src/starboard/shared/stub/drm_close_session.cc b/src/starboard/shared/stub/drm_close_session.cc
index a7832b4..544889c 100644
--- a/src/starboard/shared/stub/drm_close_session.cc
+++ b/src/starboard/shared/stub/drm_close_session.cc
@@ -17,7 +17,4 @@
 void SbDrmCloseSession(SbDrmSystem drm_system,
                        const void* session_id,
                        int session_id_size) {
-  SB_UNREFERENCED_PARAMETER(drm_system);
-  SB_UNREFERENCED_PARAMETER(session_id);
-  SB_UNREFERENCED_PARAMETER(session_id_size);
 }
diff --git a/src/starboard/shared/stub/drm_create_system.cc b/src/starboard/shared/stub/drm_create_system.cc
index 67cdc93..ed51122 100644
--- a/src/starboard/shared/stub/drm_create_system.cc
+++ b/src/starboard/shared/stub/drm_create_system.cc
@@ -22,12 +22,5 @@
     SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback,
     SbDrmServerCertificateUpdatedFunc server_certificate_updated_callback,
     SbDrmSessionClosedFunc session_closed_callback) {
-  SB_UNREFERENCED_PARAMETER(context);
-  SB_UNREFERENCED_PARAMETER(key_system);
-  SB_UNREFERENCED_PARAMETER(update_request_callback);
-  SB_UNREFERENCED_PARAMETER(session_updated_callback);
-  SB_UNREFERENCED_PARAMETER(key_statuses_changed_callback);
-  SB_UNREFERENCED_PARAMETER(server_certificate_updated_callback);
-  SB_UNREFERENCED_PARAMETER(session_closed_callback);
   return kSbDrmSystemInvalid;
 }
diff --git a/src/starboard/shared/stub/drm_destroy_system.cc b/src/starboard/shared/stub/drm_destroy_system.cc
index 85e1b73..22f5aef 100644
--- a/src/starboard/shared/stub/drm_destroy_system.cc
+++ b/src/starboard/shared/stub/drm_destroy_system.cc
@@ -15,5 +15,4 @@
 #include "starboard/drm.h"
 
 void SbDrmDestroySystem(SbDrmSystem drm_system) {
-  SB_UNREFERENCED_PARAMETER(drm_system);
 }
diff --git a/src/starboard/shared/stub/drm_generate_session_update_request.cc b/src/starboard/shared/stub/drm_generate_session_update_request.cc
index f0e9621..623257c 100644
--- a/src/starboard/shared/stub/drm_generate_session_update_request.cc
+++ b/src/starboard/shared/stub/drm_generate_session_update_request.cc
@@ -14,9 +14,8 @@
 
 #include "starboard/drm.h"
 
-void SbDrmGenerateSessionUpdateRequest(SbDrmSystem /*drm_system*/,
-                                       int /*ticket*/,
-                                       const char* /*type*/,
-                                       const void* /*initialization_data*/,
-                                       int /*initialization_data_size*/) {
-}
+void SbDrmGenerateSessionUpdateRequest(SbDrmSystem drm_system,
+                                       int ticket,
+                                       const char* type,
+                                       const void* initialization_data,
+                                       int initialization_data_size) {}
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/shared/stub/drm_get_metrics.cc
similarity index 67%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/shared/stub/drm_get_metrics.cc
index 0fbc0ef..dc11009 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/shared/stub/drm_get_metrics.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#include "starboard/drm.h"
 
-#include "starboard/raspi/shared/atomic_public.h"
+#if SB_API_VERSION >= 12
 
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+const void* SbDrmGetMetrics(SbDrmSystem drm_system, int* size) {
+  if (size != NULL) {
+    *size = 0;
+  }
+
+  return NULL;
+}
+
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/shared/stub/drm_is_server_certificate_updatable.cc b/src/starboard/shared/stub/drm_is_server_certificate_updatable.cc
index 8169bd6..f03988c 100644
--- a/src/starboard/shared/stub/drm_is_server_certificate_updatable.cc
+++ b/src/starboard/shared/stub/drm_is_server_certificate_updatable.cc
@@ -15,7 +15,5 @@
 #include "starboard/drm.h"
 
 bool SbDrmIsServerCertificateUpdatable(SbDrmSystem drm_system) {
-  SB_UNREFERENCED_PARAMETER(drm_system);
-
   return false;
 }
diff --git a/src/starboard/shared/stub/drm_update_server_certificate.cc b/src/starboard/shared/stub/drm_update_server_certificate.cc
index 635b6ef..8d4d97b 100644
--- a/src/starboard/shared/stub/drm_update_server_certificate.cc
+++ b/src/starboard/shared/stub/drm_update_server_certificate.cc
@@ -18,8 +18,4 @@
                                   int ticket,
                                   const void* certificate,
                                   int certificate_size) {
-  SB_UNREFERENCED_PARAMETER(drm_system);
-  SB_UNREFERENCED_PARAMETER(ticket);
-  SB_UNREFERENCED_PARAMETER(certificate);
-  SB_UNREFERENCED_PARAMETER(certificate_size);
 }
diff --git a/src/starboard/shared/stub/drm_update_session.cc b/src/starboard/shared/stub/drm_update_session.cc
index 7b0811e..8ee51dc 100644
--- a/src/starboard/shared/stub/drm_update_session.cc
+++ b/src/starboard/shared/stub/drm_update_session.cc
@@ -14,10 +14,9 @@
 
 #include "starboard/drm.h"
 
-void SbDrmUpdateSession(SbDrmSystem /*drm_system*/,
-                        int /*ticket*/,
-                        const void* /*key*/,
-                        int /*key_size*/,
-                        const void* /*session_id*/,
-                        int /*session_id_size*/) {
-}
+void SbDrmUpdateSession(SbDrmSystem drm_system,
+                        int ticket,
+                        const void* key,
+                        int key_size,
+                        const void* session_id,
+                        int session_id_size) {}
diff --git a/src/starboard/shared/stub/file_atomic_replace.cc b/src/starboard/shared/stub/file_atomic_replace.cc
index 636b1e8..e365f0f 100644
--- a/src/starboard/shared/stub/file_atomic_replace.cc
+++ b/src/starboard/shared/stub/file_atomic_replace.cc
@@ -14,12 +14,12 @@
 
 #include "starboard/file.h"
 
-#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#if SB_API_VERSION >= 12
 
-bool SbFileAtomicReplace(const char* /* path */,
-                         const char* /* data */,
-                         int64_t /* data_size */) {
+bool SbFileAtomicReplace(const char* path,
+                         const char* data,
+                         int64_t data_size) {
   return false;
 }
 
-#endif  // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/shared/stub/file_can_open.cc b/src/starboard/shared/stub/file_can_open.cc
index 9676b28..7335af2 100644
--- a/src/starboard/shared/stub/file_can_open.cc
+++ b/src/starboard/shared/stub/file_can_open.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/file.h"
 
-bool SbFileCanOpen(const char* /*path*/, int /*flags*/) {
+bool SbFileCanOpen(const char* path, int flags) {
   return false;
 }
diff --git a/src/starboard/shared/stub/file_close.cc b/src/starboard/shared/stub/file_close.cc
index 272edb2..47df9f2 100644
--- a/src/starboard/shared/stub/file_close.cc
+++ b/src/starboard/shared/stub/file_close.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/file.h"
 
-bool SbFileClose(SbFile /*file*/) {
+bool SbFileClose(SbFile file) {
   return false;
 }
diff --git a/src/starboard/shared/stub/file_delete.cc b/src/starboard/shared/stub/file_delete.cc
index 2961c8c..ff3225f 100644
--- a/src/starboard/shared/stub/file_delete.cc
+++ b/src/starboard/shared/stub/file_delete.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/file.h"
 
-bool SbFileDelete(const char* /*path*/) {
+bool SbFileDelete(const char* path) {
   return false;
 }
diff --git a/src/starboard/shared/stub/file_exists.cc b/src/starboard/shared/stub/file_exists.cc
index d7e3433..1207137 100644
--- a/src/starboard/shared/stub/file_exists.cc
+++ b/src/starboard/shared/stub/file_exists.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/file.h"
 
-bool SbFileExists(const char* /*path*/) {
+bool SbFileExists(const char* path) {
   return false;
 }
diff --git a/src/starboard/shared/stub/file_flush.cc b/src/starboard/shared/stub/file_flush.cc
index d82de93..5598957 100644
--- a/src/starboard/shared/stub/file_flush.cc
+++ b/src/starboard/shared/stub/file_flush.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/file.h"
 
-bool SbFileFlush(SbFile /*file*/) {
+bool SbFileFlush(SbFile file) {
   return false;
 }
diff --git a/src/starboard/shared/stub/file_get_info.cc b/src/starboard/shared/stub/file_get_info.cc
index 3758378..40cf2ee 100644
--- a/src/starboard/shared/stub/file_get_info.cc
+++ b/src/starboard/shared/stub/file_get_info.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/file.h"
 
-bool SbFileGetInfo(SbFile /*file*/, SbFileInfo* /*out_info*/) {
+bool SbFileGetInfo(SbFile file, SbFileInfo* out_info) {
   return false;
 }
diff --git a/src/starboard/shared/stub/file_get_path_info.cc b/src/starboard/shared/stub/file_get_path_info.cc
index 3b0a88e..c42bce7 100644
--- a/src/starboard/shared/stub/file_get_path_info.cc
+++ b/src/starboard/shared/stub/file_get_path_info.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/file.h"
 
-bool SbFileGetPathInfo(const char* /*path*/, SbFileInfo* /*out_info*/) {
+bool SbFileGetPathInfo(const char* path, SbFileInfo* out_info) {
   return false;
 }
diff --git a/src/starboard/shared/stub/file_open.cc b/src/starboard/shared/stub/file_open.cc
index da135a9..fe3332b 100644
--- a/src/starboard/shared/stub/file_open.cc
+++ b/src/starboard/shared/stub/file_open.cc
@@ -14,9 +14,9 @@
 
 #include "starboard/file.h"
 
-SbFile SbFileOpen(const char* /*path*/,
-                  int /*flags*/,
-                  bool* /*out_created*/,
-                  SbFileError* /*out_error*/) {
+SbFile SbFileOpen(const char* path,
+                  int flags,
+                  bool* out_created,
+                  SbFileError* out_error) {
   return kSbFileInvalid;
 }
diff --git a/src/starboard/shared/stub/file_read.cc b/src/starboard/shared/stub/file_read.cc
index a20fad7..4bf6065 100644
--- a/src/starboard/shared/stub/file_read.cc
+++ b/src/starboard/shared/stub/file_read.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/file.h"
 
-int SbFileRead(SbFile /*file*/, char* /*data*/, int /*size*/) {
+int SbFileRead(SbFile file, char* data, int size) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/file_seek.cc b/src/starboard/shared/stub/file_seek.cc
index 6fad7f2..ac2dc24 100644
--- a/src/starboard/shared/stub/file_seek.cc
+++ b/src/starboard/shared/stub/file_seek.cc
@@ -14,8 +14,6 @@
 
 #include "starboard/file.h"
 
-int64_t SbFileSeek(SbFile /*file*/,
-                   SbFileWhence /*whence*/,
-                   int64_t /*offset*/) {
+int64_t SbFileSeek(SbFile file, SbFileWhence whence, int64_t offset) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/file_truncate.cc b/src/starboard/shared/stub/file_truncate.cc
index 0d1fb9f..b65a8cc 100644
--- a/src/starboard/shared/stub/file_truncate.cc
+++ b/src/starboard/shared/stub/file_truncate.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/file.h"
 
-bool SbFileTruncate(SbFile /*file*/, int64_t /*length*/) {
+bool SbFileTruncate(SbFile file, int64_t length) {
   return false;
 }
diff --git a/src/starboard/shared/stub/file_write.cc b/src/starboard/shared/stub/file_write.cc
index 75d18e0..d6e7858 100644
--- a/src/starboard/shared/stub/file_write.cc
+++ b/src/starboard/shared/stub/file_write.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/file.h"
 
-int SbFileWrite(SbFile /*file*/, const char* /*data*/, int /*size*/) {
+int SbFileWrite(SbFile file, const char* data, int size) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/image_decode.cc b/src/starboard/shared/stub/image_decode.cc
index e3a2043..9fdadf6 100644
--- a/src/starboard/shared/stub/image_decode.cc
+++ b/src/starboard/shared/stub/image_decode.cc
@@ -20,10 +20,5 @@
                              int data_size,
                              const char* mime_type,
                              SbDecodeTargetFormat format) {
-  SB_UNREFERENCED_PARAMETER(data);
-  SB_UNREFERENCED_PARAMETER(data_size);
-  SB_UNREFERENCED_PARAMETER(format);
-  SB_UNREFERENCED_PARAMETER(mime_type);
-  SB_UNREFERENCED_PARAMETER(provider);
   return kSbDecodeTargetInvalid;
 }
diff --git a/src/starboard/shared/stub/image_is_decode_supported.cc b/src/starboard/shared/stub/image_is_decode_supported.cc
index 9e04d60..acffa29 100644
--- a/src/starboard/shared/stub/image_is_decode_supported.cc
+++ b/src/starboard/shared/stub/image_is_decode_supported.cc
@@ -17,7 +17,5 @@
 
 bool SbImageIsDecodeSupported(const char* mime_type,
                               SbDecodeTargetFormat format) {
-  SB_UNREFERENCED_PARAMETER(mime_type);
-  SB_UNREFERENCED_PARAMETER(format);
   return false;
 }
diff --git a/src/starboard/shared/stub/log.cc b/src/starboard/shared/stub/log.cc
index d506d68..8718f90 100644
--- a/src/starboard/shared/stub/log.cc
+++ b/src/starboard/shared/stub/log.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/common/log.h"
 
-void SbLog(SbLogPriority /*priority*/, const char* /*message*/) {
-}
+void SbLog(SbLogPriority priority, const char* message) {}
diff --git a/src/starboard/shared/stub/log_format.cc b/src/starboard/shared/stub/log_format.cc
index e88e5cc..876f764 100644
--- a/src/starboard/shared/stub/log_format.cc
+++ b/src/starboard/shared/stub/log_format.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/common/log.h"
 
-void SbLogFormat(const char* /*format*/, va_list /*arguments*/) {
-}
+void SbLogFormat(const char* format, va_list arguments) {}
diff --git a/src/starboard/shared/stub/log_raw.cc b/src/starboard/shared/stub/log_raw.cc
index f942177..503ffc9 100644
--- a/src/starboard/shared/stub/log_raw.cc
+++ b/src/starboard/shared/stub/log_raw.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/common/log.h"
 
-void SbLogRaw(const char* /*message*/) {
-}
+void SbLogRaw(const char* message) {}
diff --git a/src/starboard/shared/stub/log_raw_dump_stack.cc b/src/starboard/shared/stub/log_raw_dump_stack.cc
index 699861b..e2bb485 100644
--- a/src/starboard/shared/stub/log_raw_dump_stack.cc
+++ b/src/starboard/shared/stub/log_raw_dump_stack.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/common/log.h"
 
-void SbLogRawDumpStack(int /*frames_to_skip*/) {
-}
+void SbLogRawDumpStack(int frames_to_skip) {}
diff --git a/src/starboard/shared/stub/log_raw_format.cc b/src/starboard/shared/stub/log_raw_format.cc
index 2a25551..1b3b18d 100644
--- a/src/starboard/shared/stub/log_raw_format.cc
+++ b/src/starboard/shared/stub/log_raw_format.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/common/log.h"
 
-void SbLogRawFormat(const char* /*format*/, va_list /*arguments*/) {
-}
+void SbLogRawFormat(const char* format, va_list arguments) {}
diff --git a/src/starboard/shared/stub/media_can_play_mime_and_key_system.cc b/src/starboard/shared/stub/media_can_play_mime_and_key_system.cc
index 26c291e..d9fd1c3 100644
--- a/src/starboard/shared/stub/media_can_play_mime_and_key_system.cc
+++ b/src/starboard/shared/stub/media_can_play_mime_and_key_system.cc
@@ -16,7 +16,5 @@
 
 SbMediaSupportType SbMediaCanPlayMimeAndKeySystem(const char* mime,
                                                   const char* key_system) {
-  SB_UNREFERENCED_PARAMETER(mime);
-  SB_UNREFERENCED_PARAMETER(key_system);
   return kSbMediaSupportTypeNotSupported;
 }
diff --git a/src/starboard/shared/stub/media_get_audio_configuration.cc b/src/starboard/shared/stub/media_get_audio_configuration.cc
index ce54817..3dd16ce 100644
--- a/src/starboard/shared/stub/media_get_audio_configuration.cc
+++ b/src/starboard/shared/stub/media_get_audio_configuration.cc
@@ -17,7 +17,5 @@
 bool SbMediaGetAudioConfiguration(
     int output_index,
     SbMediaAudioConfiguration* out_configuration) {
-  SB_UNREFERENCED_PARAMETER(output_index);
-  SB_UNREFERENCED_PARAMETER(out_configuration);
   return false;
 }
diff --git a/src/starboard/shared/stub/media_get_buffer_alignment.cc b/src/starboard/shared/stub/media_get_buffer_alignment.cc
index 7569a47..607d895 100644
--- a/src/starboard/shared/stub/media_get_buffer_alignment.cc
+++ b/src/starboard/shared/stub/media_get_buffer_alignment.cc
@@ -15,6 +15,5 @@
 #include "starboard/media.h"
 
 int SbMediaGetBufferAlignment(SbMediaType type) {
-  SB_UNREFERENCED_PARAMETER(type);
   return 0;
 }
diff --git a/src/starboard/shared/stub/media_get_buffer_padding.cc b/src/starboard/shared/stub/media_get_buffer_padding.cc
index 3384e9f..6c4ead1 100644
--- a/src/starboard/shared/stub/media_get_buffer_padding.cc
+++ b/src/starboard/shared/stub/media_get_buffer_padding.cc
@@ -15,6 +15,5 @@
 #include "starboard/media.h"
 
 int SbMediaGetBufferPadding(SbMediaType type) {
-  SB_UNREFERENCED_PARAMETER(type);
   return 0;
 }
diff --git a/src/starboard/shared/stub/media_get_max_buffer_capacity.cc b/src/starboard/shared/stub/media_get_max_buffer_capacity.cc
index b1ca4d2..c157adb 100644
--- a/src/starboard/shared/stub/media_get_max_buffer_capacity.cc
+++ b/src/starboard/shared/stub/media_get_max_buffer_capacity.cc
@@ -18,9 +18,5 @@
                                 int resolution_width,
                                 int resolution_height,
                                 int bits_per_pixel) {
-  SB_UNREFERENCED_PARAMETER(codec);
-  SB_UNREFERENCED_PARAMETER(resolution_width);
-  SB_UNREFERENCED_PARAMETER(resolution_height);
-  SB_UNREFERENCED_PARAMETER(bits_per_pixel);
   return 0;
 }
diff --git a/src/starboard/shared/stub/media_get_progressive_buffer_budget.cc b/src/starboard/shared/stub/media_get_progressive_buffer_budget.cc
index 2b79d56..a780c4f 100644
--- a/src/starboard/shared/stub/media_get_progressive_buffer_budget.cc
+++ b/src/starboard/shared/stub/media_get_progressive_buffer_budget.cc
@@ -18,9 +18,5 @@
                                       int resolution_width,
                                       int resolution_height,
                                       int bits_per_pixel) {
-  SB_UNREFERENCED_PARAMETER(codec);
-  SB_UNREFERENCED_PARAMETER(resolution_width);
-  SB_UNREFERENCED_PARAMETER(resolution_height);
-  SB_UNREFERENCED_PARAMETER(bits_per_pixel);
   return 0;
 }
diff --git a/src/starboard/shared/stub/media_get_video_buffer_budget.cc b/src/starboard/shared/stub/media_get_video_buffer_budget.cc
index 65c320a..990fc44 100644
--- a/src/starboard/shared/stub/media_get_video_buffer_budget.cc
+++ b/src/starboard/shared/stub/media_get_video_buffer_budget.cc
@@ -18,9 +18,5 @@
                                 int resolution_width,
                                 int resolution_height,
                                 int bits_per_pixel) {
-  SB_UNREFERENCED_PARAMETER(codec);
-  SB_UNREFERENCED_PARAMETER(resolution_width);
-  SB_UNREFERENCED_PARAMETER(resolution_height);
-  SB_UNREFERENCED_PARAMETER(bits_per_pixel);
   return 0;
 }
diff --git a/src/starboard/shared/stub/media_is_audio_supported.cc b/src/starboard/shared/stub/media_is_audio_supported.cc
index c180d4f..00187ee 100644
--- a/src/starboard/shared/stub/media_is_audio_supported.cc
+++ b/src/starboard/shared/stub/media_is_audio_supported.cc
@@ -16,10 +16,10 @@
 
 #include "starboard/media.h"
 
-bool SbMediaIsAudioSupported(SbMediaAudioCodec /*audio_codec*/,
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
-                             const char* /*content_type*/,
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
-                             int64_t /*bitrate*/) {
+bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
+#if SB_API_VERSION >= 12
+                             const char* content_type,
+#endif  // SB_API_VERSION >= 12
+                             int64_t bitrate) {
   return false;
 }
diff --git a/src/starboard/shared/stub/media_is_supported.cc b/src/starboard/shared/stub/media_is_supported.cc
index 884ffda..accde4b 100644
--- a/src/starboard/shared/stub/media_is_supported.cc
+++ b/src/starboard/shared/stub/media_is_supported.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/media.h"
 
-bool SbMediaIsSupported(SbMediaVideoCodec /*video_codec*/,
-                        SbMediaAudioCodec /*audio_codec*/,
-                        const char* /*key_system*/) {
+bool SbMediaIsSupported(SbMediaVideoCodec video_codec,
+                        SbMediaAudioCodec audio_codec,
+                        const char* key_system) {
   return false;
 }
diff --git a/src/starboard/shared/stub/media_is_transfer_characteristics_supported.cc b/src/starboard/shared/stub/media_is_transfer_characteristics_supported.cc
index e62b8e0..e278733 100644
--- a/src/starboard/shared/stub/media_is_transfer_characteristics_supported.cc
+++ b/src/starboard/shared/stub/media_is_transfer_characteristics_supported.cc
@@ -17,8 +17,7 @@
 #include "starboard/media.h"
 
 #if !SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
-bool SbMediaIsTransferCharacteristicsSupported(
-    SbMediaTransferId /*transfer_id*/) {
+bool SbMediaIsTransferCharacteristicsSupported(SbMediaTransferId transfer_id) {
   return false;
 }
 #endif  // !SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
diff --git a/src/starboard/shared/stub/media_is_video_supported.cc b/src/starboard/shared/stub/media_is_video_supported.cc
index eaeb8ad..e7d2f4c 100644
--- a/src/starboard/shared/stub/media_is_video_supported.cc
+++ b/src/starboard/shared/stub/media_is_video_supported.cc
@@ -16,22 +16,22 @@
 
 #include "starboard/media.h"
 
-bool SbMediaIsVideoSupported(SbMediaVideoCodec /*video_codec*/,
-#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
-                             const char* /*content_type*/,
-#endif  // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
+#if SB_API_VERSION >= 12
+                             const char* content_type,
+#endif  // SB_API_VERSION >= 12
 #if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
-                             int /*profile*/,
-                             int /*level*/,
-                             int /*bit_depth*/,
-                             SbMediaPrimaryId /*primary_id*/,
-                             SbMediaTransferId /*transfer_id*/,
-                             SbMediaMatrixId /*matrix_id*/,
+                             int profile,
+                             int level,
+                             int bit_depth,
+                             SbMediaPrimaryId primary_id,
+                             SbMediaTransferId transfer_id,
+                             SbMediaMatrixId matrix_id,
 #endif  // SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
-                             int /*frame_width*/,
-                             int /*frame_height*/,
-                             int64_t /*bitrate*/,
-                             int /*fps*/,
-                             bool /*decode_to_texture_required*/) {
+                             int frame_width,
+                             int frame_height,
+                             int64_t bitrate,
+                             int fps,
+                             bool decode_to_texture_required) {
   return false;
 }
diff --git a/src/starboard/shared/stub/media_set_output_protection.cc b/src/starboard/shared/stub/media_set_output_protection.cc
index 5ab6a20..19a886b 100644
--- a/src/starboard/shared/stub/media_set_output_protection.cc
+++ b/src/starboard/shared/stub/media_set_output_protection.cc
@@ -17,6 +17,5 @@
 #include "starboard/common/log.h"
 
 bool SbMediaSetOutputProtection(bool enabled) {
-  SB_UNREFERENCED_PARAMETER(enabled);
   return false;
 }
diff --git a/src/starboard/shared/stub/memory_allocate_aligned_unchecked.cc b/src/starboard/shared/stub/memory_allocate_aligned_unchecked.cc
index 9adf2ac..079b2ca 100644
--- a/src/starboard/shared/stub/memory_allocate_aligned_unchecked.cc
+++ b/src/starboard/shared/stub/memory_allocate_aligned_unchecked.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/memory.h"
 
-void* SbMemoryAllocateAlignedUnchecked(size_t /*alignment*/, size_t /*size*/) {
+void* SbMemoryAllocateAlignedUnchecked(size_t alignment, size_t size) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/memory_allocate_unchecked.cc b/src/starboard/shared/stub/memory_allocate_unchecked.cc
index 60d049f..4e9867b 100644
--- a/src/starboard/shared/stub/memory_allocate_unchecked.cc
+++ b/src/starboard/shared/stub/memory_allocate_unchecked.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/memory.h"
 
-void* SbMemoryAllocateUnchecked(size_t /*size*/) {
+void* SbMemoryAllocateUnchecked(size_t size) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/memory_compare.cc b/src/starboard/shared/stub/memory_compare.cc
index e2a736c..6f8c3a4 100644
--- a/src/starboard/shared/stub/memory_compare.cc
+++ b/src/starboard/shared/stub/memory_compare.cc
@@ -14,7 +14,6 @@
 
 #include "starboard/memory.h"
 
-int SbMemoryCompare(const void* /*buffer1*/, const void* /*buffer2*/,
-                    size_t /*count*/) {
+int SbMemoryCompare(const void* buffer1, const void* buffer2, size_t count) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/memory_copy.cc b/src/starboard/shared/stub/memory_copy.cc
index 7479f33..2101911 100644
--- a/src/starboard/shared/stub/memory_copy.cc
+++ b/src/starboard/shared/stub/memory_copy.cc
@@ -14,7 +14,6 @@
 
 #include "starboard/memory.h"
 
-void* SbMemoryCopy(void* /*destination*/, const void* /*source*/,
-                   size_t /*count*/) {
+void* SbMemoryCopy(void* destination, const void* source, size_t count) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/memory_find_byte.cc b/src/starboard/shared/stub/memory_find_byte.cc
index 9dc4e87..3587394 100644
--- a/src/starboard/shared/stub/memory_find_byte.cc
+++ b/src/starboard/shared/stub/memory_find_byte.cc
@@ -14,7 +14,6 @@
 
 #include "starboard/memory.h"
 
-const void* SbMemoryFindByte(const void* /*buffer*/, int /*value*/,
-                             size_t /*count*/) {
+const void* SbMemoryFindByte(const void* buffer, int value, size_t count) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/memory_flush.cc b/src/starboard/shared/stub/memory_flush.cc
index 8651aa4..b3299ef 100644
--- a/src/starboard/shared/stub/memory_flush.cc
+++ b/src/starboard/shared/stub/memory_flush.cc
@@ -14,4 +14,4 @@
 
 #include "starboard/memory.h"
 
-void SbMemoryFlush(void* /*virtual_address*/, int64_t /*size_bytes*/) {}
+void SbMemoryFlush(void* virtual_address, int64_t size_bytes) {}
diff --git a/src/starboard/shared/stub/memory_free.cc b/src/starboard/shared/stub/memory_free.cc
index 4cdbb07..2c64702 100644
--- a/src/starboard/shared/stub/memory_free.cc
+++ b/src/starboard/shared/stub/memory_free.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/memory.h"
 
-void SbMemoryFree(void* /*memory*/) {
-}
+void SbMemoryFree(void* memory) {}
diff --git a/src/starboard/shared/stub/memory_free_aligned.cc b/src/starboard/shared/stub/memory_free_aligned.cc
index 656669a..dd31fcc 100644
--- a/src/starboard/shared/stub/memory_free_aligned.cc
+++ b/src/starboard/shared/stub/memory_free_aligned.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/memory.h"
 
-void SbMemoryFreeAligned(void* /*memory*/) {
-}
+void SbMemoryFreeAligned(void* memory) {}
diff --git a/src/starboard/shared/stub/memory_get_stack_bounds.cc b/src/starboard/shared/stub/memory_get_stack_bounds.cc
index 0994c77..b614513 100644
--- a/src/starboard/shared/stub/memory_get_stack_bounds.cc
+++ b/src/starboard/shared/stub/memory_get_stack_bounds.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/memory.h"
 
-void SbMemoryGetStackBounds(void** /*out_high*/, void** /*out_low*/) {
-}
+void SbMemoryGetStackBounds(void** out_high, void** out_low) {}
diff --git a/src/starboard/shared/stub/memory_map.cc b/src/starboard/shared/stub/memory_map.cc
index aa8a95b..c8a9124 100644
--- a/src/starboard/shared/stub/memory_map.cc
+++ b/src/starboard/shared/stub/memory_map.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/memory.h"
 
-void* SbMemoryMap(int64_t /*size_bytes*/, int /*flags*/, const char* /*name*/) {
+void* SbMemoryMap(int64_t size_bytes, int flags, const char* name) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/memory_move.cc b/src/starboard/shared/stub/memory_move.cc
index c513b53..277fc11 100644
--- a/src/starboard/shared/stub/memory_move.cc
+++ b/src/starboard/shared/stub/memory_move.cc
@@ -14,7 +14,6 @@
 
 #include "starboard/memory.h"
 
-void* SbMemoryMove(void* /*destination*/, const void* /*source*/,
-                   size_t /*count*/) {
+void* SbMemoryMove(void* destination, const void* source, size_t count) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/memory_protect.cc b/src/starboard/shared/stub/memory_protect.cc
index 99ca1e9..ebd1a08 100644
--- a/src/starboard/shared/stub/memory_protect.cc
+++ b/src/starboard/shared/stub/memory_protect.cc
@@ -15,8 +15,6 @@
 #include "starboard/configuration.h"
 #include "starboard/memory.h"
 
-bool SbMemoryProtect(void* /*virtual_address*/,
-                     int64_t /*size_bytes*/,
-                     int /*flags*/) {
+bool SbMemoryProtect(void* virtual_address, int64_t size_bytes, int flags) {
   return false;
 }
diff --git a/src/starboard/shared/stub/memory_reallocate_unchecked.cc b/src/starboard/shared/stub/memory_reallocate_unchecked.cc
index af5c3e8..a9c121b 100644
--- a/src/starboard/shared/stub/memory_reallocate_unchecked.cc
+++ b/src/starboard/shared/stub/memory_reallocate_unchecked.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/memory.h"
 
-void* SbMemoryReallocateUnchecked(void* /*memory*/, size_t /*size*/) {
+void* SbMemoryReallocateUnchecked(void* memory, size_t size) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/memory_set.cc b/src/starboard/shared/stub/memory_set.cc
index b4b8a9a..7c21bef 100644
--- a/src/starboard/shared/stub/memory_set.cc
+++ b/src/starboard/shared/stub/memory_set.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/memory.h"
 
-void* SbMemorySet(void* /*destination*/, int /*byte_value*/, size_t /*count*/) {
+void* SbMemorySet(void* destination, int byte_value, size_t count) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/memory_unmap.cc b/src/starboard/shared/stub/memory_unmap.cc
index a98e0f5..0d7de48 100644
--- a/src/starboard/shared/stub/memory_unmap.cc
+++ b/src/starboard/shared/stub/memory_unmap.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/memory.h"
 
-bool SbMemoryUnmap(void* /*virtual_address*/, int64_t /*size_bytes*/) {
+bool SbMemoryUnmap(void* virtual_address, int64_t size_bytes) {
   return false;
 }
diff --git a/src/starboard/shared/stub/mutex_acquire.cc b/src/starboard/shared/stub/mutex_acquire.cc
index 4274573..cede4d1 100644
--- a/src/starboard/shared/stub/mutex_acquire.cc
+++ b/src/starboard/shared/stub/mutex_acquire.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/mutex.h"
 
-SbMutexResult SbMutexAcquire(SbMutex* /*mutex*/) {
+SbMutexResult SbMutexAcquire(SbMutex* mutex) {
   return kSbMutexDestroyed;
 }
diff --git a/src/starboard/shared/stub/mutex_acquire_try.cc b/src/starboard/shared/stub/mutex_acquire_try.cc
index 651d5e9..a9f1ba8 100644
--- a/src/starboard/shared/stub/mutex_acquire_try.cc
+++ b/src/starboard/shared/stub/mutex_acquire_try.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/mutex.h"
 
-SbMutexResult SbMutexAcquireTry(SbMutex* /*mutex*/) {
+SbMutexResult SbMutexAcquireTry(SbMutex* mutex) {
   return kSbMutexDestroyed;
 }
diff --git a/src/starboard/shared/stub/mutex_create.cc b/src/starboard/shared/stub/mutex_create.cc
index da24d7d..11586de 100644
--- a/src/starboard/shared/stub/mutex_create.cc
+++ b/src/starboard/shared/stub/mutex_create.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/mutex.h"
 
-bool SbMutexCreate(SbMutex* /*mutex*/) {
+bool SbMutexCreate(SbMutex* mutex) {
   return false;
 }
diff --git a/src/starboard/shared/stub/mutex_destroy.cc b/src/starboard/shared/stub/mutex_destroy.cc
index 71b5478..7922ddd 100644
--- a/src/starboard/shared/stub/mutex_destroy.cc
+++ b/src/starboard/shared/stub/mutex_destroy.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/mutex.h"
 
-bool SbMutexDestroy(SbMutex* /*mutex*/) {
+bool SbMutexDestroy(SbMutex* mutex) {
   return false;
 }
diff --git a/src/starboard/shared/stub/mutex_release.cc b/src/starboard/shared/stub/mutex_release.cc
index e1ad6f5..88e6071 100644
--- a/src/starboard/shared/stub/mutex_release.cc
+++ b/src/starboard/shared/stub/mutex_release.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/mutex.h"
 
-bool SbMutexRelease(SbMutex* /*mutex*/) {
+bool SbMutexRelease(SbMutex* mutex) {
   return false;
 }
diff --git a/src/starboard/shared/stub/once.cc b/src/starboard/shared/stub/once.cc
index d429ca0..7ff1559 100644
--- a/src/starboard/shared/stub/once.cc
+++ b/src/starboard/shared/stub/once.cc
@@ -14,7 +14,6 @@
 
 #include "starboard/once.h"
 
-bool SbOnce(SbOnceControl* /*once_control*/,
-            SbOnceInitRoutine /*init_routine*/) {
+bool SbOnce(SbOnceControl* once_control, SbOnceInitRoutine init_routine) {
   return false;
 }
diff --git a/src/starboard/shared/stub/player_create.cc b/src/starboard/shared/stub/player_create.cc
index a5a905f..2fa455a 100644
--- a/src/starboard/shared/stub/player_create.cc
+++ b/src/starboard/shared/stub/player_create.cc
@@ -19,34 +19,34 @@
 #if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 
 SbPlayer SbPlayerCreate(
-    SbWindow /*window*/,
-    const SbPlayerCreationParam* /*creation_param*/,
-    SbPlayerDeallocateSampleFunc /*sample_deallocate_func*/,
-    SbPlayerDecoderStatusFunc /*decoder_status_func*/,
-    SbPlayerStatusFunc /*player_status_func*/,
-    SbPlayerErrorFunc /*player_error_func*/,
-    void* /*context*/,
-    SbDecodeTargetGraphicsContextProvider* /*context_provider*/) {
+    SbWindow window,
+    const SbPlayerCreationParam* creation_param,
+    SbPlayerDeallocateSampleFunc sample_deallocate_func,
+    SbPlayerDecoderStatusFunc decoder_status_func,
+    SbPlayerStatusFunc player_status_func,
+    SbPlayerErrorFunc player_error_func,
+    void* context,
+    SbDecodeTargetGraphicsContextProvider* context_provider) {
   return kSbPlayerInvalid;
 }
 
 #else  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 
-SbPlayer SbPlayerCreate(SbWindow /*window*/,
-                        SbMediaVideoCodec /*video_codec*/,
-                        SbMediaAudioCodec /*audio_codec*/,
-                        SbDrmSystem /*drm_system*/,
-                        const SbMediaAudioSampleInfo* /*audio_sample_info*/,
+SbPlayer SbPlayerCreate(SbWindow window,
+                        SbMediaVideoCodec video_codec,
+                        SbMediaAudioCodec audio_codec,
+                        SbDrmSystem drm_system,
+                        const SbMediaAudioSampleInfo* audio_sample_info,
 #if SB_API_VERSION >= 11
-                        const char* /*max_video_capabilities*/,
+                        const char* max_video_capabilities,
 #endif  // SB_API_VERSION >= 11
-                        SbPlayerDeallocateSampleFunc /*sample_deallocate_func*/,
-                        SbPlayerDecoderStatusFunc /*decoder_status_func*/,
-                        SbPlayerStatusFunc /*player_status_func*/,
-                        SbPlayerErrorFunc /*player_error_func*/,
-                        void* /*context*/,
-                        SbPlayerOutputMode /*output_mode*/,
-                        SbDecodeTargetGraphicsContextProvider* /*provider*/) {
+                        SbPlayerDeallocateSampleFunc sample_deallocate_func,
+                        SbPlayerDecoderStatusFunc decoder_status_func,
+                        SbPlayerStatusFunc player_status_func,
+                        SbPlayerErrorFunc player_error_func,
+                        void* context,
+                        SbPlayerOutputMode output_mode,
+                        SbDecodeTargetGraphicsContextProvider* provider) {
   return kSbPlayerInvalid;
 }
 
diff --git a/src/starboard/shared/stub/player_destroy.cc b/src/starboard/shared/stub/player_destroy.cc
index 2dadb83..b8bb1f8 100644
--- a/src/starboard/shared/stub/player_destroy.cc
+++ b/src/starboard/shared/stub/player_destroy.cc
@@ -14,4 +14,4 @@
 
 #include "starboard/player.h"
 
-void SbPlayerDestroy(SbPlayer /*player*/) {}
+void SbPlayerDestroy(SbPlayer player) {}
diff --git a/src/starboard/shared/stub/player_get_current_frame.cc b/src/starboard/shared/stub/player_get_current_frame.cc
index cbe0575..ab730b0 100644
--- a/src/starboard/shared/stub/player_get_current_frame.cc
+++ b/src/starboard/shared/stub/player_get_current_frame.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/player.h"
 
-SbDecodeTarget SbPlayerGetCurrentFrame(SbPlayer /*player*/) {
+SbDecodeTarget SbPlayerGetCurrentFrame(SbPlayer player) {
   return kSbDecodeTargetInvalid;
 }
diff --git a/src/starboard/shared/stub/player_get_info2.cc b/src/starboard/shared/stub/player_get_info2.cc
index 4b443c1..4f5dae8 100644
--- a/src/starboard/shared/stub/player_get_info2.cc
+++ b/src/starboard/shared/stub/player_get_info2.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/player.h"
 
-void SbPlayerGetInfo2(SbPlayer /*player*/, SbPlayerInfo2* /*out_player_info*/) {
-}
+void SbPlayerGetInfo2(SbPlayer player, SbPlayerInfo2* out_player_info) {}
diff --git a/src/starboard/shared/stub/player_get_maximum_number_of_samples_per_write.cc b/src/starboard/shared/stub/player_get_maximum_number_of_samples_per_write.cc
index ebba599..2722200 100644
--- a/src/starboard/shared/stub/player_get_maximum_number_of_samples_per_write.cc
+++ b/src/starboard/shared/stub/player_get_maximum_number_of_samples_per_write.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/player.h"
 
-int SbPlayerGetMaximumNumberOfSamplesPerWrite(SbPlayer /*player*/,
-                                              SbMediaType /*sample_type*/) {
+int SbPlayerGetMaximumNumberOfSamplesPerWrite(SbPlayer player,
+                                              SbMediaType sample_type) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/player_get_preferred_output_mode.cc b/src/starboard/shared/stub/player_get_preferred_output_mode.cc
index f52fcc3..8d55e5d 100644
--- a/src/starboard/shared/stub/player_get_preferred_output_mode.cc
+++ b/src/starboard/shared/stub/player_get_preferred_output_mode.cc
@@ -19,7 +19,7 @@
 #if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 
 SbPlayerOutputMode SbPlayerGetPreferredOutputMode(
-    const SbPlayerCreationParam* /*creation_param*/) {
+    const SbPlayerCreationParam* creation_param) {
   return kSbPlayerOutputModeInvalid;
 }
 
diff --git a/src/starboard/shared/stub/player_output_mode_supported.cc b/src/starboard/shared/stub/player_output_mode_supported.cc
index 2b470fa..24e4149 100644
--- a/src/starboard/shared/stub/player_output_mode_supported.cc
+++ b/src/starboard/shared/stub/player_output_mode_supported.cc
@@ -16,9 +16,9 @@
 
 #if !SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 
-bool SbPlayerOutputModeSupported(SbPlayerOutputMode /*output_mode*/,
-                                 SbMediaVideoCodec /*codec*/,
-                                 SbDrmSystem /*drm_system*/) {
+bool SbPlayerOutputModeSupported(SbPlayerOutputMode output_mod /,
+                                 SbMediaVideoCodec codec,
+                                 SbDrmSystem drm_system) {
   return false;
 }
 
diff --git a/src/starboard/shared/stub/player_seek2.cc b/src/starboard/shared/stub/player_seek2.cc
index 23e4b82..b931802 100644
--- a/src/starboard/shared/stub/player_seek2.cc
+++ b/src/starboard/shared/stub/player_seek2.cc
@@ -14,6 +14,4 @@
 
 #include "starboard/player.h"
 
-void SbPlayerSeek2(SbPlayer /*player*/,
-                   SbTime /*seek_to_timestamp*/,
-                   int /*ticket*/) {}
+void SbPlayerSeek2(SbPlayer player, SbTime seek_to_timestamp, int ticket) {}
diff --git a/src/starboard/shared/stub/player_set_bounds.cc b/src/starboard/shared/stub/player_set_bounds.cc
index 5818b6d..bc90691 100644
--- a/src/starboard/shared/stub/player_set_bounds.cc
+++ b/src/starboard/shared/stub/player_set_bounds.cc
@@ -14,10 +14,9 @@
 
 #include "starboard/player.h"
 
-void SbPlayerSetBounds(SbPlayer /*player*/,
-                       int /*z_index*/,
-                       int /*x*/,
-                       int /*y*/,
-                       int /*width*/,
-                       int /*height*/) {
-}
+void SbPlayerSetBounds(SbPlayer player,
+                       int z_index,
+                       int x,
+                       int y,
+                       int width,
+                       int height) {}
diff --git a/src/starboard/shared/stub/player_set_playback_rate.cc b/src/starboard/shared/stub/player_set_playback_rate.cc
index 8696f2a..d0d5182 100644
--- a/src/starboard/shared/stub/player_set_playback_rate.cc
+++ b/src/starboard/shared/stub/player_set_playback_rate.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/player.h"
 
-bool SbPlayerSetPlaybackRate(SbPlayer /*player*/, double /*playback_rate*/) {
+bool SbPlayerSetPlaybackRate(SbPlayer player, double playback_rate) {
   return false;
 }
diff --git a/src/starboard/shared/stub/player_set_volume.cc b/src/starboard/shared/stub/player_set_volume.cc
index 069fd04..2fc2732 100644
--- a/src/starboard/shared/stub/player_set_volume.cc
+++ b/src/starboard/shared/stub/player_set_volume.cc
@@ -14,4 +14,4 @@
 
 #include "starboard/player.h"
 
-void SbPlayerSetVolume(SbPlayer /*player*/, double /*volume*/) {}
+void SbPlayerSetVolume(SbPlayer player, double volume) {}
diff --git a/src/starboard/shared/stub/player_write_end_of_stream.cc b/src/starboard/shared/stub/player_write_end_of_stream.cc
index 7903d58..586904c 100644
--- a/src/starboard/shared/stub/player_write_end_of_stream.cc
+++ b/src/starboard/shared/stub/player_write_end_of_stream.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/player.h"
 
-void SbPlayerWriteEndOfStream(SbPlayer /*player*/,
-                              SbMediaType /*stream_type*/) {}
+void SbPlayerWriteEndOfStream(SbPlayer player, SbMediaType stream_type) {}
diff --git a/src/starboard/shared/stub/player_write_sample2.cc b/src/starboard/shared/stub/player_write_sample2.cc
index 4ed00c4..50ec297 100644
--- a/src/starboard/shared/stub/player_write_sample2.cc
+++ b/src/starboard/shared/stub/player_write_sample2.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/player.h"
 
-void SbPlayerWriteSample2(SbPlayer /*player*/,
-                          SbMediaType /*sample_type*/,
-                          const SbPlayerSampleInfo* /*sample_infos*/,
-                          int /*number_of_sample_infos*/) {}
+void SbPlayerWriteSample2(SbPlayer player,
+                          SbMediaType sample_type,
+                          const SbPlayerSampleInfo* sample_infos,
+                          int number_of_sample_infos) {}
diff --git a/src/starboard/shared/stub/socket_accept.cc b/src/starboard/shared/stub/socket_accept.cc
index 49cbead..b03587f 100644
--- a/src/starboard/shared/stub/socket_accept.cc
+++ b/src/starboard/shared/stub/socket_accept.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-SbSocket SbSocketAccept(SbSocket /*socket*/) {
+SbSocket SbSocketAccept(SbSocket socket) {
   return kSbSocketInvalid;
 }
diff --git a/src/starboard/shared/stub/socket_bind.cc b/src/starboard/shared/stub/socket_bind.cc
index 504d8b6..69702d6 100644
--- a/src/starboard/shared/stub/socket_bind.cc
+++ b/src/starboard/shared/stub/socket_bind.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/common/socket.h"
 
-SbSocketError SbSocketBind(SbSocket /*socket*/,
-                           const SbSocketAddress* /*local_address*/) {
+SbSocketError SbSocketBind(SbSocket socket,
+                           const SbSocketAddress* local_address) {
   return kSbSocketErrorFailed;
 }
diff --git a/src/starboard/shared/stub/socket_clear_last_error.cc b/src/starboard/shared/stub/socket_clear_last_error.cc
index 0ab1eea..03419f5 100644
--- a/src/starboard/shared/stub/socket_clear_last_error.cc
+++ b/src/starboard/shared/stub/socket_clear_last_error.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketClearLastError(SbSocket /*socket*/) {
+bool SbSocketClearLastError(SbSocket socket) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_connect.cc b/src/starboard/shared/stub/socket_connect.cc
index b617723..5c7dd56 100644
--- a/src/starboard/shared/stub/socket_connect.cc
+++ b/src/starboard/shared/stub/socket_connect.cc
@@ -14,7 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-SbSocketError SbSocketConnect(SbSocket /*socket*/,
-                              const SbSocketAddress* /*address*/) {
+SbSocketError SbSocketConnect(SbSocket socket, const SbSocketAddress* address) {
   return kSbSocketErrorFailed;
 }
diff --git a/src/starboard/shared/stub/socket_create.cc b/src/starboard/shared/stub/socket_create.cc
index 10ef252..d563aef 100644
--- a/src/starboard/shared/stub/socket_create.cc
+++ b/src/starboard/shared/stub/socket_create.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/common/socket.h"
 
-SbSocket SbSocketCreate(SbSocketAddressType /*address_type*/,
-                        SbSocketProtocol /*protocol*/) {
+SbSocket SbSocketCreate(SbSocketAddressType address_type,
+                        SbSocketProtocol protocol) {
   return kSbSocketInvalid;
 }
diff --git a/src/starboard/shared/stub/socket_destroy.cc b/src/starboard/shared/stub/socket_destroy.cc
index 980ce81..577b3f0 100644
--- a/src/starboard/shared/stub/socket_destroy.cc
+++ b/src/starboard/shared/stub/socket_destroy.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketDestroy(SbSocket /*socket*/) {
+bool SbSocketDestroy(SbSocket socket) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_free_resolution.cc b/src/starboard/shared/stub/socket_free_resolution.cc
index f8ce474..4f34a15 100644
--- a/src/starboard/shared/stub/socket_free_resolution.cc
+++ b/src/starboard/shared/stub/socket_free_resolution.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/common/socket.h"
 
-void SbSocketFreeResolution(SbSocketResolution* /*resolution*/) {
-}
+void SbSocketFreeResolution(SbSocketResolution* resolution) {}
diff --git a/src/starboard/shared/stub/socket_get_interface_address.cc b/src/starboard/shared/stub/socket_get_interface_address.cc
index 0908597..6057b6e 100644
--- a/src/starboard/shared/stub/socket_get_interface_address.cc
+++ b/src/starboard/shared/stub/socket_get_interface_address.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketGetInterfaceAddress(const SbSocketAddress* const /*destination*/,
-                                 SbSocketAddress* /*out_source_address*/,
-                                 SbSocketAddress* /*out_netmask*/) {
+bool SbSocketGetInterfaceAddress(const SbSocketAddress* const destination,
+                                 SbSocketAddress* out_source_address,
+                                 SbSocketAddress* out_netmask) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_get_last_error.cc b/src/starboard/shared/stub/socket_get_last_error.cc
index 4d644b8..75debe1 100644
--- a/src/starboard/shared/stub/socket_get_last_error.cc
+++ b/src/starboard/shared/stub/socket_get_last_error.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-SbSocketError SbSocketGetLastError(SbSocket /*socket*/) {
+SbSocketError SbSocketGetLastError(SbSocket socket) {
   return kSbSocketErrorFailed;
 }
diff --git a/src/starboard/shared/stub/socket_get_local_address.cc b/src/starboard/shared/stub/socket_get_local_address.cc
index 7d09596..c921e5c 100644
--- a/src/starboard/shared/stub/socket_get_local_address.cc
+++ b/src/starboard/shared/stub/socket_get_local_address.cc
@@ -14,7 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketGetLocalAddress(SbSocket /*socket*/,
-                             SbSocketAddress* /*out_address*/) {
+bool SbSocketGetLocalAddress(SbSocket socket, SbSocketAddress* out_address) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_is_connected.cc b/src/starboard/shared/stub/socket_is_connected.cc
index 32d108e..33cfe81 100644
--- a/src/starboard/shared/stub/socket_is_connected.cc
+++ b/src/starboard/shared/stub/socket_is_connected.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketIsConnected(SbSocket /*socket*/) {
+bool SbSocketIsConnected(SbSocket socket) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_is_connected_and_idle.cc b/src/starboard/shared/stub/socket_is_connected_and_idle.cc
index 65cab49..a2001a3 100644
--- a/src/starboard/shared/stub/socket_is_connected_and_idle.cc
+++ b/src/starboard/shared/stub/socket_is_connected_and_idle.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketIsConnectedAndIdle(SbSocket /*socket*/) {
+bool SbSocketIsConnectedAndIdle(SbSocket socket) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_is_ipv6_supported.cc b/src/starboard/shared/stub/socket_is_ipv6_supported.cc
index c79a7b3..64cac7e 100644
--- a/src/starboard/shared/stub/socket_is_ipv6_supported.cc
+++ b/src/starboard/shared/stub/socket_is_ipv6_supported.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/socket.h"
 
-#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbSocketIsIpv6Supported() {
   return false;
diff --git a/src/starboard/shared/stub/socket_join_multicast_group.cc b/src/starboard/shared/stub/socket_join_multicast_group.cc
index f8037ba..ae57ab5 100644
--- a/src/starboard/shared/stub/socket_join_multicast_group.cc
+++ b/src/starboard/shared/stub/socket_join_multicast_group.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketJoinMulticastGroup(SbSocket /*socket*/,
-                                const SbSocketAddress* /*address*/) {
+bool SbSocketJoinMulticastGroup(SbSocket socket,
+                                const SbSocketAddress* address) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_listen.cc b/src/starboard/shared/stub/socket_listen.cc
index debcc9f..b4b29d4 100644
--- a/src/starboard/shared/stub/socket_listen.cc
+++ b/src/starboard/shared/stub/socket_listen.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-SbSocketError SbSocketListen(SbSocket /*socket*/) {
+SbSocketError SbSocketListen(SbSocket socket) {
   return kSbSocketErrorFailed;
 }
diff --git a/src/starboard/shared/stub/socket_receive_from.cc b/src/starboard/shared/stub/socket_receive_from.cc
index 683b2b8..b8d407d 100644
--- a/src/starboard/shared/stub/socket_receive_from.cc
+++ b/src/starboard/shared/stub/socket_receive_from.cc
@@ -14,9 +14,9 @@
 
 #include "starboard/common/socket.h"
 
-int SbSocketReceiveFrom(SbSocket /*socket*/,
-                        char* /*out_data*/,
-                        int /*data_size*/,
-                        SbSocketAddress* /*out_source*/) {
+int SbSocketReceiveFrom(SbSocket socket,
+                        char* out_data,
+                        int data_size,
+                        SbSocketAddress* out_source) {
   return -1;
 }
diff --git a/src/starboard/shared/stub/socket_resolve.cc b/src/starboard/shared/stub/socket_resolve.cc
index 7c36c70..51ad4c2 100644
--- a/src/starboard/shared/stub/socket_resolve.cc
+++ b/src/starboard/shared/stub/socket_resolve.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-SbSocketResolution* SbSocketResolve(const char* /*hostname*/, int /*filters*/) {
+SbSocketResolution* SbSocketResolve(const char* hostname, int filters) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/socket_send_to.cc b/src/starboard/shared/stub/socket_send_to.cc
index a17dbb2..d1e3882 100644
--- a/src/starboard/shared/stub/socket_send_to.cc
+++ b/src/starboard/shared/stub/socket_send_to.cc
@@ -14,9 +14,9 @@
 
 #include "starboard/common/socket.h"
 
-int SbSocketSendTo(SbSocket /*socket*/,
-                   const char* /*data*/,
-                   int /*data_size*/,
-                   const SbSocketAddress* /*destination*/) {
+int SbSocketSendTo(SbSocket socket,
+                   const char* data,
+                   int data_size,
+                   const SbSocketAddress* destination) {
   return -1;
 }
diff --git a/src/starboard/shared/stub/socket_set_broadcast.cc b/src/starboard/shared/stub/socket_set_broadcast.cc
index 2ca3730..9ce4e74 100644
--- a/src/starboard/shared/stub/socket_set_broadcast.cc
+++ b/src/starboard/shared/stub/socket_set_broadcast.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketSetBroadcast(SbSocket /*socket*/, bool /*value*/) {
+bool SbSocketSetBroadcast(SbSocket socket, bool value) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_set_receive_buffer_size.cc b/src/starboard/shared/stub/socket_set_receive_buffer_size.cc
index 00b0ca9..70cca39 100644
--- a/src/starboard/shared/stub/socket_set_receive_buffer_size.cc
+++ b/src/starboard/shared/stub/socket_set_receive_buffer_size.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketSetReceiveBufferSize(SbSocket /*socket*/, int32_t /*size*/) {
+bool SbSocketSetReceiveBufferSize(SbSocket socket, int32_t size) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_set_reuse_address.cc b/src/starboard/shared/stub/socket_set_reuse_address.cc
index 2917032..aa13449 100644
--- a/src/starboard/shared/stub/socket_set_reuse_address.cc
+++ b/src/starboard/shared/stub/socket_set_reuse_address.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketSetReuseAddress(SbSocket /*socket*/, bool /*value*/) {
+bool SbSocketSetReuseAddress(SbSocket socket, bool value) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_set_send_buffer_size.cc b/src/starboard/shared/stub/socket_set_send_buffer_size.cc
index 134f85b..9476284 100644
--- a/src/starboard/shared/stub/socket_set_send_buffer_size.cc
+++ b/src/starboard/shared/stub/socket_set_send_buffer_size.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketSetSendBufferSize(SbSocket /*socket*/, int32_t /*size*/) {
+bool SbSocketSetSendBufferSize(SbSocket socket, int32_t size) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_set_tcp_keep_alive.cc b/src/starboard/shared/stub/socket_set_tcp_keep_alive.cc
index e93f7c3..16f9be3 100644
--- a/src/starboard/shared/stub/socket_set_tcp_keep_alive.cc
+++ b/src/starboard/shared/stub/socket_set_tcp_keep_alive.cc
@@ -14,8 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketSetTcpKeepAlive(SbSocket /*socket*/,
-                             bool /*value*/,
-                             SbTime /*period*/) {
+bool SbSocketSetTcpKeepAlive(SbSocket socket, bool value, SbTime period) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_set_tcp_no_delay.cc b/src/starboard/shared/stub/socket_set_tcp_no_delay.cc
index df2c77c..b029558 100644
--- a/src/starboard/shared/stub/socket_set_tcp_no_delay.cc
+++ b/src/starboard/shared/stub/socket_set_tcp_no_delay.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketSetTcpNoDelay(SbSocket /*socket*/, bool /*value*/) {
+bool SbSocketSetTcpNoDelay(SbSocket socket, bool value) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_set_tcp_window_scaling.cc b/src/starboard/shared/stub/socket_set_tcp_window_scaling.cc
index 51733a6..769c136 100644
--- a/src/starboard/shared/stub/socket_set_tcp_window_scaling.cc
+++ b/src/starboard/shared/stub/socket_set_tcp_window_scaling.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/socket.h"
 
-bool SbSocketSetTcpWindowScaling(SbSocket /*socket*/, bool /*value*/) {
+bool SbSocketSetTcpWindowScaling(SbSocket socket, bool value) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_waiter_add.cc b/src/starboard/shared/stub/socket_waiter_add.cc
index 139f7ca..20949e9 100644
--- a/src/starboard/shared/stub/socket_waiter_add.cc
+++ b/src/starboard/shared/stub/socket_waiter_add.cc
@@ -14,11 +14,11 @@
 
 #include "starboard/socket_waiter.h"
 
-bool SbSocketWaiterAdd(SbSocketWaiter /*waiter*/,
-                       SbSocket /*socket*/,
-                       void* /*context*/,
-                       SbSocketWaiterCallback /*callback*/,
-                       int /*interests*/,
-                       bool /*persistent*/) {
+bool SbSocketWaiterAdd(SbSocketWaiter waiter,
+                       SbSocket socket,
+                       void* context,
+                       SbSocketWaiterCallback callback,
+                       int interests,
+                       bool persistent) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_waiter_destroy.cc b/src/starboard/shared/stub/socket_waiter_destroy.cc
index 2e48439..16232f1 100644
--- a/src/starboard/shared/stub/socket_waiter_destroy.cc
+++ b/src/starboard/shared/stub/socket_waiter_destroy.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/socket_waiter.h"
 
-bool SbSocketWaiterDestroy(SbSocketWaiter /*waiter*/) {
+bool SbSocketWaiterDestroy(SbSocketWaiter waiter) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_waiter_remove.cc b/src/starboard/shared/stub/socket_waiter_remove.cc
index bcba068..4a8406e 100644
--- a/src/starboard/shared/stub/socket_waiter_remove.cc
+++ b/src/starboard/shared/stub/socket_waiter_remove.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/socket_waiter.h"
 
-bool SbSocketWaiterRemove(SbSocketWaiter /*waiter*/, SbSocket /*socket*/) {
+bool SbSocketWaiterRemove(SbSocketWaiter waiter, SbSocket socket) {
   return false;
 }
diff --git a/src/starboard/shared/stub/socket_waiter_wait.cc b/src/starboard/shared/stub/socket_waiter_wait.cc
index b357d1c..04022b2 100644
--- a/src/starboard/shared/stub/socket_waiter_wait.cc
+++ b/src/starboard/shared/stub/socket_waiter_wait.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/socket_waiter.h"
 
-void SbSocketWaiterWait(SbSocketWaiter /*waiter*/) {
-}
+void SbSocketWaiterWait(SbSocketWaiter waiter) {}
diff --git a/src/starboard/shared/stub/socket_waiter_wait_timed.cc b/src/starboard/shared/stub/socket_waiter_wait_timed.cc
index 57e62ff..f742ab4 100644
--- a/src/starboard/shared/stub/socket_waiter_wait_timed.cc
+++ b/src/starboard/shared/stub/socket_waiter_wait_timed.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/socket_waiter.h"
 
-SbSocketWaiterResult SbSocketWaiterWaitTimed(SbSocketWaiter /*waiter*/,
-                                             SbTime /*duration*/) {
+SbSocketWaiterResult SbSocketWaiterWaitTimed(SbSocketWaiter waiter,
+                                             SbTime duration) {
   return kSbSocketWaiterResultInvalid;
 }
diff --git a/src/starboard/shared/stub/socket_waiter_wake_up.cc b/src/starboard/shared/stub/socket_waiter_wake_up.cc
index b87c836..012a924 100644
--- a/src/starboard/shared/stub/socket_waiter_wake_up.cc
+++ b/src/starboard/shared/stub/socket_waiter_wake_up.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/socket_waiter.h"
 
-void SbSocketWaiterWakeUp(SbSocketWaiter /*waiter*/) {
-}
+void SbSocketWaiterWakeUp(SbSocketWaiter waiter) {}
diff --git a/src/starboard/shared/stub/speech_recognizer_cancel.cc b/src/starboard/shared/stub/speech_recognizer_cancel.cc
index e85ee0a..74d85c1 100644
--- a/src/starboard/shared/stub/speech_recognizer_cancel.cc
+++ b/src/starboard/shared/stub/speech_recognizer_cancel.cc
@@ -14,11 +14,10 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
-void SbSpeechRecognizerCancel(SbSpeechRecognizer /*recognizer*/) {}
+void SbSpeechRecognizerCancel(SbSpeechRecognizer recognizer) {}
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/stub/speech_recognizer_create.cc b/src/starboard/shared/stub/speech_recognizer_create.cc
index 3064a22..e273b84 100644
--- a/src/starboard/shared/stub/speech_recognizer_create.cc
+++ b/src/starboard/shared/stub/speech_recognizer_create.cc
@@ -14,14 +14,13 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 SbSpeechRecognizer SbSpeechRecognizerCreate(
-    const SbSpeechRecognizerHandler* /*handler*/) {
+    const SbSpeechRecognizerHandler* handler) {
   return kSbSpeechRecognizerInvalid;
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/stub/speech_recognizer_destroy.cc b/src/starboard/shared/stub/speech_recognizer_destroy.cc
index 8f4d056..a6ddb1f 100644
--- a/src/starboard/shared/stub/speech_recognizer_destroy.cc
+++ b/src/starboard/shared/stub/speech_recognizer_destroy.cc
@@ -14,11 +14,10 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
-void SbSpeechRecognizerDestroy(SbSpeechRecognizer /*recognizer*/) {}
+void SbSpeechRecognizerDestroy(SbSpeechRecognizer recognizer) {}
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/stub/speech_recognizer_is_supported.cc b/src/starboard/shared/stub/speech_recognizer_is_supported.cc
index 84d7a49..3122b73 100644
--- a/src/starboard/shared/stub/speech_recognizer_is_supported.cc
+++ b/src/starboard/shared/stub/speech_recognizer_is_supported.cc
@@ -14,10 +14,10 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbSpeechRecognizerIsSupported() {
   return false;
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/shared/stub/speech_recognizer_start.cc b/src/starboard/shared/stub/speech_recognizer_start.cc
index b80ebea..a64fbca 100644
--- a/src/starboard/shared/stub/speech_recognizer_start.cc
+++ b/src/starboard/shared/stub/speech_recognizer_start.cc
@@ -14,14 +14,13 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
-bool SbSpeechRecognizerStart(SbSpeechRecognizer /*recognizer*/,
-                             const SbSpeechConfiguration* /*configuration*/) {
+bool SbSpeechRecognizerStart(SbSpeechRecognizer recognizer,
+                             const SbSpeechConfiguration* configuration) {
   return false;
 }
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/stub/speech_recognizer_stop.cc b/src/starboard/shared/stub/speech_recognizer_stop.cc
index ad9f63a..9f381b1 100644
--- a/src/starboard/shared/stub/speech_recognizer_stop.cc
+++ b/src/starboard/shared/stub/speech_recognizer_stop.cc
@@ -14,11 +14,10 @@
 
 #include "starboard/speech_recognizer.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
-void SbSpeechRecognizerStop(SbSpeechRecognizer /*recognizer*/) {}
+void SbSpeechRecognizerStop(SbSpeechRecognizer recognizer) {}
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/stub/speech_synthesis_cancel.cc b/src/starboard/shared/stub/speech_synthesis_cancel.cc
index c9b9712..e640713 100644
--- a/src/starboard/shared/stub/speech_synthesis_cancel.cc
+++ b/src/starboard/shared/stub/speech_synthesis_cancel.cc
@@ -14,8 +14,7 @@
 
 #include "starboard/speech_synthesis.h"
 
-#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_SYNTHESIS)
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_SYNTHESIS)
 
 void SbSpeechSynthesisCancel() {}
 
diff --git a/src/starboard/shared/stub/speech_synthesis_is_supported.cc b/src/starboard/shared/stub/speech_synthesis_is_supported.cc
index d82c1b7..8d998a7 100644
--- a/src/starboard/shared/stub/speech_synthesis_is_supported.cc
+++ b/src/starboard/shared/stub/speech_synthesis_is_supported.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/speech_synthesis.h"
 
-#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbSpeechSynthesisIsSupported() {
   return false;
diff --git a/src/starboard/shared/stub/speech_synthesis_speak.cc b/src/starboard/shared/stub/speech_synthesis_speak.cc
index d11cf31..1b5fdde 100644
--- a/src/starboard/shared/stub/speech_synthesis_speak.cc
+++ b/src/starboard/shared/stub/speech_synthesis_speak.cc
@@ -14,8 +14,7 @@
 
 #include "starboard/speech_synthesis.h"
 
-#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_SYNTHESIS)
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_SYNTHESIS)
 
 void SbSpeechSynthesisSpeak(const char* text) {}
 
diff --git a/src/starboard/shared/stub/storage_close_record.cc b/src/starboard/shared/stub/storage_close_record.cc
index 6404ae8..3578e38 100644
--- a/src/starboard/shared/stub/storage_close_record.cc
+++ b/src/starboard/shared/stub/storage_close_record.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/storage.h"
 
-bool SbStorageCloseRecord(SbStorageRecord /*record*/) {
+bool SbStorageCloseRecord(SbStorageRecord record) {
   return false;
 }
diff --git a/src/starboard/shared/stub/storage_delete_record.cc b/src/starboard/shared/stub/storage_delete_record.cc
index 6289c1f..b56a2cd 100644
--- a/src/starboard/shared/stub/storage_delete_record.cc
+++ b/src/starboard/shared/stub/storage_delete_record.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/storage.h"
 
-bool SbStorageDeleteRecord(SbUser /*user*/, const char* /*name*/) {
+bool SbStorageDeleteRecord(SbUser user, const char* name) {
   return false;
 }
diff --git a/src/starboard/shared/stub/storage_get_record_size.cc b/src/starboard/shared/stub/storage_get_record_size.cc
index f78de7e..454be71 100644
--- a/src/starboard/shared/stub/storage_get_record_size.cc
+++ b/src/starboard/shared/stub/storage_get_record_size.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/storage.h"
 
-int64_t SbStorageGetRecordSize(SbStorageRecord /*record*/) {
+int64_t SbStorageGetRecordSize(SbStorageRecord record) {
   return -1;
 }
diff --git a/src/starboard/shared/stub/storage_open_record.cc b/src/starboard/shared/stub/storage_open_record.cc
index 4c9c05d..dcf27bf 100644
--- a/src/starboard/shared/stub/storage_open_record.cc
+++ b/src/starboard/shared/stub/storage_open_record.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/storage.h"
 
-SbStorageRecord SbStorageOpenRecord(SbUser /*user*/, const char* /*name*/) {
+SbStorageRecord SbStorageOpenRecord(SbUser user, const char* name) {
   return kSbStorageInvalidRecord;
 }
diff --git a/src/starboard/shared/stub/storage_read_record.cc b/src/starboard/shared/stub/storage_read_record.cc
index 566e1c6..9cd93ba 100644
--- a/src/starboard/shared/stub/storage_read_record.cc
+++ b/src/starboard/shared/stub/storage_read_record.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/common/storage.h"
 
-int64_t SbStorageReadRecord(SbStorageRecord /*record*/,
-                            char* /*out_data*/,
-                            int64_t /*data_size*/) {
+int64_t SbStorageReadRecord(SbStorageRecord record,
+                            char* out_data,
+                            int64_t data_size) {
   return -1;
 }
diff --git a/src/starboard/shared/stub/storage_write_record.cc b/src/starboard/shared/stub/storage_write_record.cc
index 6c14b79..6ba3072 100644
--- a/src/starboard/shared/stub/storage_write_record.cc
+++ b/src/starboard/shared/stub/storage_write_record.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/common/storage.h"
 
-bool SbStorageWriteRecord(SbStorageRecord /*record*/,
-                          const char* /*data*/,
-                          int64_t /*data_size*/) {
+bool SbStorageWriteRecord(SbStorageRecord record,
+                          const char* data,
+                          int64_t data_size) {
   return false;
 }
diff --git a/src/starboard/shared/stub/string_compare.cc b/src/starboard/shared/stub/string_compare.cc
index 97b6009..ac5fcc9 100644
--- a/src/starboard/shared/stub/string_compare.cc
+++ b/src/starboard/shared/stub/string_compare.cc
@@ -14,8 +14,6 @@
 
 #include "starboard/common/string.h"
 
-int SbStringCompare(const char* /*string1*/,
-                    const char* /*string2*/,
-                    size_t /*count*/) {
+int SbStringCompare(const char* string1, const char* string2, size_t count) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/string_compare_all.cc b/src/starboard/shared/stub/string_compare_all.cc
index d3f9b23..3c445c1 100644
--- a/src/starboard/shared/stub/string_compare_all.cc
+++ b/src/starboard/shared/stub/string_compare_all.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/string.h"
 
-int SbStringCompareAll(const char* /*string1*/, const char* /*string2*/) {
+int SbStringCompareAll(const char* string1, const char* string2) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/string_compare_no_case.cc b/src/starboard/shared/stub/string_compare_no_case.cc
index b464485..3434800 100644
--- a/src/starboard/shared/stub/string_compare_no_case.cc
+++ b/src/starboard/shared/stub/string_compare_no_case.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/string.h"
 
-int SbStringCompareNoCase(const char* /*string1*/, const char* /*string2*/) {
+int SbStringCompareNoCase(const char* string1, const char* string2) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/string_compare_no_case_n.cc b/src/starboard/shared/stub/string_compare_no_case_n.cc
index 6361eaa..e04639e 100644
--- a/src/starboard/shared/stub/string_compare_no_case_n.cc
+++ b/src/starboard/shared/stub/string_compare_no_case_n.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/common/string.h"
 
-int SbStringCompareNoCaseN(const char* /*string1*/,
-                           const char* /*string2*/,
-                           size_t /*count*/) {
+int SbStringCompareNoCaseN(const char* string1,
+                           const char* string2,
+                           size_t count) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/string_compare_wide.cc b/src/starboard/shared/stub/string_compare_wide.cc
index 40c3088..d1285e2 100644
--- a/src/starboard/shared/stub/string_compare_wide.cc
+++ b/src/starboard/shared/stub/string_compare_wide.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/common/string.h"
 
-int SbStringCompareWide(const wchar_t* /*string1*/,
-                        const wchar_t* /*string2*/,
-                        size_t /*count*/) {
+int SbStringCompareWide(const wchar_t* string1,
+                        const wchar_t* string2,
+                        size_t count) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/string_concat.cc b/src/starboard/shared/stub/string_concat.cc
index f7eeec8..f9158d0 100644
--- a/src/starboard/shared/stub/string_concat.cc
+++ b/src/starboard/shared/stub/string_concat.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/common/string.h"
 
-int SbStringConcat(char* /*out_destination*/,
-                   const char* /*source*/,
-                   int /*destination_size*/) {
+int SbStringConcat(char* out_destination,
+                   const char* source,
+                   int destination_size) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/string_concat_wide.cc b/src/starboard/shared/stub/string_concat_wide.cc
index 35ea63a..0ef185a 100644
--- a/src/starboard/shared/stub/string_concat_wide.cc
+++ b/src/starboard/shared/stub/string_concat_wide.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/common/string.h"
 
-int SbStringConcatWide(wchar_t* /*out_destination*/,
-                       const wchar_t* /*source*/,
-                       int /*destination_size*/) {
+int SbStringConcatWide(wchar_t* out_destination,
+                       const wchar_t* source,
+                       int destination_size) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/string_copy.cc b/src/starboard/shared/stub/string_copy.cc
index 127a51c..07f63dc 100644
--- a/src/starboard/shared/stub/string_copy.cc
+++ b/src/starboard/shared/stub/string_copy.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/common/string.h"
 
-int SbStringCopy(char* /*out_destination*/,
-                 const char* /*source*/,
-                 int /*destination_size*/) {
+int SbStringCopy(char* out_destination,
+                 const char* source,
+                 int destination_size) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/string_copy_wide.cc b/src/starboard/shared/stub/string_copy_wide.cc
index 4620d6a..63e92d6 100644
--- a/src/starboard/shared/stub/string_copy_wide.cc
+++ b/src/starboard/shared/stub/string_copy_wide.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/common/string.h"
 
-int SbStringCopyWide(wchar_t* /*out_destination*/,
-                     const wchar_t* /*source*/,
-                     int /*destination_size*/) {
+int SbStringCopyWide(wchar_t* out_destination,
+                     const wchar_t* source,
+                     int destination_size) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/string_duplicate.cc b/src/starboard/shared/stub/string_duplicate.cc
index 5de4b52..158a129 100644
--- a/src/starboard/shared/stub/string_duplicate.cc
+++ b/src/starboard/shared/stub/string_duplicate.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/string.h"
 
-char* SbStringDuplicate(const char* /*source*/) {
+char* SbStringDuplicate(const char* source) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/string_find_character.cc b/src/starboard/shared/stub/string_find_character.cc
index 1493e76..01c7b6b 100644
--- a/src/starboard/shared/stub/string_find_character.cc
+++ b/src/starboard/shared/stub/string_find_character.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/string.h"
 
-const char* SbStringFindCharacter(const char* /*str*/, char /*character*/) {
+const char* SbStringFindCharacter(const char* str, char character) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/string_find_last_character.cc b/src/starboard/shared/stub/string_find_last_character.cc
index dedd399..5d963aa 100644
--- a/src/starboard/shared/stub/string_find_last_character.cc
+++ b/src/starboard/shared/stub/string_find_last_character.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/string.h"
 
-const char* SbStringFindLastCharacter(const char* /*str*/, char /*character*/) {
+const char* SbStringFindLastCharacter(const char* str, char character) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/string_find_string.cc b/src/starboard/shared/stub/string_find_string.cc
index c5498c8..3dd13cc 100644
--- a/src/starboard/shared/stub/string_find_string.cc
+++ b/src/starboard/shared/stub/string_find_string.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/string.h"
 
-const char* SbStringFindString(const char* /*str1*/, const char* /*str2*/) {
+const char* SbStringFindString(const char* str1, const char* str2) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/string_format.cc b/src/starboard/shared/stub/string_format.cc
index 6f605f8..a6874ac 100644
--- a/src/starboard/shared/stub/string_format.cc
+++ b/src/starboard/shared/stub/string_format.cc
@@ -14,9 +14,9 @@
 
 #include "starboard/common/string.h"
 
-int SbStringFormat(char* /*out_buffer*/,
-                   size_t /*buffer_size*/,
-                   const char* /*format*/,
-                   va_list /*arguments*/) {
+int SbStringFormat(char* out_buffer,
+                   size_t buffer_size,
+                   const char* format,
+                   va_list arguments) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/string_format_wide.cc b/src/starboard/shared/stub/string_format_wide.cc
index 2ca96a0..150bd1b 100644
--- a/src/starboard/shared/stub/string_format_wide.cc
+++ b/src/starboard/shared/stub/string_format_wide.cc
@@ -14,9 +14,9 @@
 
 #include "starboard/common/string.h"
 
-int SbStringFormatWide(wchar_t* /*out_buffer*/,
-                       size_t /*buffer_size*/,
-                       const wchar_t* /*format*/,
-                       va_list /*arguments*/) {
+int SbStringFormatWide(wchar_t* out_buffer,
+                       size_t buffer_size,
+                       const wchar_t* format,
+                       va_list arguments) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/string_get_length.cc b/src/starboard/shared/stub/string_get_length.cc
index 7c85b15..a1f6b38 100644
--- a/src/starboard/shared/stub/string_get_length.cc
+++ b/src/starboard/shared/stub/string_get_length.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/string.h"
 
-size_t SbStringGetLength(const char* /*str*/) {
+size_t SbStringGetLength(const char* str) {
   return static_cast<size_t>(0);
 }
diff --git a/src/starboard/shared/stub/string_get_length_wide.cc b/src/starboard/shared/stub/string_get_length_wide.cc
index 443cf67..4f76f1f 100644
--- a/src/starboard/shared/stub/string_get_length_wide.cc
+++ b/src/starboard/shared/stub/string_get_length_wide.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/common/string.h"
 
-size_t SbStringGetLengthWide(const wchar_t* /*str*/) {
+size_t SbStringGetLengthWide(const wchar_t* str) {
   return static_cast<size_t>(0);
 }
diff --git a/src/starboard/shared/stub/string_parse_signed_integer.cc b/src/starboard/shared/stub/string_parse_signed_integer.cc
index 6cf6a74..de66801 100644
--- a/src/starboard/shared/stub/string_parse_signed_integer.cc
+++ b/src/starboard/shared/stub/string_parse_signed_integer.cc
@@ -15,8 +15,6 @@
 #include "starboard/common/string.h"
 
 // NOLINTNEXTLINE(runtime/int)
-long SbStringParseSignedInteger(const char* /*start*/,
-                                char** /*out_end*/,
-                                int /*base*/) {
+long SbStringParseSignedInteger(const char* start, char** out_end, int base) {
   return 0L;
 }
diff --git a/src/starboard/shared/stub/string_parse_uint64.cc b/src/starboard/shared/stub/string_parse_uint64.cc
index f7d37c8..36e2f05 100644
--- a/src/starboard/shared/stub/string_parse_uint64.cc
+++ b/src/starboard/shared/stub/string_parse_uint64.cc
@@ -14,8 +14,6 @@
 
 #include "starboard/common/string.h"
 
-uint64_t SbStringParseUInt64(const char* /*start*/,
-                             char** /*out_end*/,
-                             int /*base*/) {
+uint64_t SbStringParseUInt64(const char* start, char** out_end, int base) {
   return static_cast<uint64_t>(0);
 }
diff --git a/src/starboard/shared/stub/string_parse_unsigned_integer.cc b/src/starboard/shared/stub/string_parse_unsigned_integer.cc
index 7179297..06620dd 100644
--- a/src/starboard/shared/stub/string_parse_unsigned_integer.cc
+++ b/src/starboard/shared/stub/string_parse_unsigned_integer.cc
@@ -15,8 +15,8 @@
 #include "starboard/common/string.h"
 
 // NOLINTNEXTLINE(runtime/int)
-unsigned long SbStringParseUnsignedInteger(const char* /*start*/,
-                                           char** /*out_end*/,
-                                           int /*base*/) {
+unsigned long SbStringParseUnsignedInteger(const char* start,
+                                           char** out_end,
+                                           int base) {
   return 0UL;
 }
diff --git a/src/starboard/shared/stub/string_scan.cc b/src/starboard/shared/stub/string_scan.cc
index 05540b2..67bdc91 100644
--- a/src/starboard/shared/stub/string_scan.cc
+++ b/src/starboard/shared/stub/string_scan.cc
@@ -14,8 +14,6 @@
 
 #include "starboard/common/string.h"
 
-int SbStringScan(const char* /*buffer*/,
-                 const char* /*pattern*/,
-                 va_list /*arguments*/) {
+int SbStringScan(const char* buffer, const char* pattern, va_list arguments) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/system_binary_search.cc b/src/starboard/shared/stub/system_binary_search.cc
index 1122e9c..4b9e36b 100644
--- a/src/starboard/shared/stub/system_binary_search.cc
+++ b/src/starboard/shared/stub/system_binary_search.cc
@@ -14,10 +14,10 @@
 
 #include "starboard/system.h"
 
-void* SbSystemBinarySearch(const void* /*key*/,
-                           const void* /*base*/,
-                           size_t /*element_count*/,
-                           size_t /*element_width*/,
-                           SbSystemComparator /*comparator*/) {
+void* SbSystemBinarySearch(const void* key,
+                           const void* base,
+                           size_t element_count,
+                           size_t element_width,
+                           SbSystemComparator comparator) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/system_get_error_string.cc b/src/starboard/shared/stub/system_get_error_string.cc
index fdc792d..44aecb0 100644
--- a/src/starboard/shared/stub/system_get_error_string.cc
+++ b/src/starboard/shared/stub/system_get_error_string.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/system.h"
 
-int SbSystemGetErrorString(SbSystemError /*error*/,
-                           char* /*out_string*/,
-                           int /*string_length*/) {
+int SbSystemGetErrorString(SbSystemError error,
+                           char* out_string,
+                           int string_length) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/system_get_path.cc b/src/starboard/shared/stub/system_get_path.cc
index fd82ff6..55cb7df 100644
--- a/src/starboard/shared/stub/system_get_path.cc
+++ b/src/starboard/shared/stub/system_get_path.cc
@@ -14,7 +14,6 @@
 
 #include "starboard/system.h"
 
-bool SbSystemGetPath(SbSystemPathId /*path_id*/, char* /*out_path*/,
-                     int /*path_size*/) {
+bool SbSystemGetPath(SbSystemPathId path_id, char* out_path, int path_size) {
   return false;
 }
diff --git a/src/starboard/shared/stub/system_get_property.cc b/src/starboard/shared/stub/system_get_property.cc
index 6e6b164..05afd29 100644
--- a/src/starboard/shared/stub/system_get_property.cc
+++ b/src/starboard/shared/stub/system_get_property.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/system.h"
 
-bool SbSystemGetProperty(SbSystemPropertyId /*property_id*/,
-                         char* /*out_value*/,
-                         int /*value_length*/) {
+bool SbSystemGetProperty(SbSystemPropertyId property_id,
+                         char* out_value,
+                         int value_length) {
   return false;
 }
diff --git a/src/starboard/shared/stub/system_get_random_data.cc b/src/starboard/shared/stub/system_get_random_data.cc
index 74f1e76..705efe6 100644
--- a/src/starboard/shared/stub/system_get_random_data.cc
+++ b/src/starboard/shared/stub/system_get_random_data.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/system.h"
 
-void SbSystemGetRandomData(void* /*out_buffer*/, int /*buffer_size*/) {
-}
+void SbSystemGetRandomData(void* out_buffer, int buffer_size) {}
diff --git a/src/starboard/shared/stub/system_get_stack.cc b/src/starboard/shared/stub/system_get_stack.cc
index d058814..1bd293e 100644
--- a/src/starboard/shared/stub/system_get_stack.cc
+++ b/src/starboard/shared/stub/system_get_stack.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/system.h"
 
-int SbSystemGetStack(void** /*out_stack*/, int /*stack_size*/) {
+int SbSystemGetStack(void** out_stack, int stack_size) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/system_has_capability.cc b/src/starboard/shared/stub/system_has_capability.cc
index 9be2404..863be20 100644
--- a/src/starboard/shared/stub/system_has_capability.cc
+++ b/src/starboard/shared/stub/system_has_capability.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/system.h"
 
-bool SbSystemHasCapability(SbSystemCapabilityId /*capability_id*/) {
+bool SbSystemHasCapability(SbSystemCapabilityId capability_id) {
   return false;
 }
diff --git a/src/starboard/shared/stub/system_is_tv_device_type.cc b/src/starboard/shared/stub/system_is_tv_device_type.cc
index 0c1db5e..50905a4 100644
--- a/src/starboard/shared/stub/system_is_tv_device_type.cc
+++ b/src/starboard/shared/stub/system_is_tv_device_type.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/system.h"
 
-SbSystemDeviceType SbSystemGetDeviceType(SbSystemDeviceType /*device_type*/) {
+SbSystemDeviceType SbSystemGetDeviceType(SbSystemDeviceType device_type) {
   return false;
 }
diff --git a/src/starboard/shared/stub/system_raise_platform_error.cc b/src/starboard/shared/stub/system_raise_platform_error.cc
index 3879dbd..e2cfaf4 100644
--- a/src/starboard/shared/stub/system_raise_platform_error.cc
+++ b/src/starboard/shared/stub/system_raise_platform_error.cc
@@ -21,8 +21,6 @@
     SbSystemPlatformErrorType type,
     SbSystemPlatformErrorCallback callback,
     void* user_data) {
-  SB_UNREFERENCED_PARAMETER(callback);
-  SB_UNREFERENCED_PARAMETER(user_data);
   std::string message;
   switch (type) {
     case kSbSystemPlatformErrorTypeConnectionError:
@@ -39,8 +37,6 @@
 bool SbSystemRaisePlatformError(SbSystemPlatformErrorType type,
                                 SbSystemPlatformErrorCallback callback,
                                 void* user_data) {
-  SB_UNREFERENCED_PARAMETER(callback);
-  SB_UNREFERENCED_PARAMETER(user_data);
   std::string message;
   switch (type) {
     case kSbSystemPlatformErrorTypeConnectionError:
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/shared/stub/system_request_blur.cc
similarity index 63%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/shared/stub/system_request_blur.cc
index 0fbc0ef..3f2bcc0 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/shared/stub/system_request_blur.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#include "starboard/system.h"
 
-#include "starboard/raspi/shared/atomic_public.h"
-
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void SbSystemRequestBlur() {
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/shared/stub/system_request_conceal.cc
similarity index 62%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/shared/stub/system_request_conceal.cc
index 0fbc0ef..3008668 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/shared/stub/system_request_conceal.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#include "starboard/system.h"
 
-#include "starboard/raspi/shared/atomic_public.h"
-
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void SbSystemRequestConceal() {
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/shared/stub/system_request_focus.cc
similarity index 63%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/shared/stub/system_request_focus.cc
index 0fbc0ef..78d7054 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/shared/stub/system_request_focus.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#include "starboard/system.h"
 
-#include "starboard/raspi/shared/atomic_public.h"
-
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void SbSystemRequestFocus() {
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/shared/stub/system_request_freeze.cc
similarity index 62%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/shared/stub/system_request_freeze.cc
index 0fbc0ef..b1a8b2b 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/shared/stub/system_request_freeze.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#include "starboard/system.h"
 
-#include "starboard/raspi/shared/atomic_public.h"
-
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void SbSystemRequestFreeze() {
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/stub/system_request_pause.cc b/src/starboard/shared/stub/system_request_pause.cc
index 206ea25..1de51fd 100644
--- a/src/starboard/shared/stub/system_request_pause.cc
+++ b/src/starboard/shared/stub/system_request_pause.cc
@@ -14,5 +14,9 @@
 
 #include "starboard/system.h"
 
+#if SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION && \
+    !SB_HAS(CONCEALED_STATE)
 void SbSystemRequestPause() {
 }
+#endif  // SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION &&
+        // !SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/shared/stub/system_request_reveal.cc
similarity index 62%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/shared/stub/system_request_reveal.cc
index 0fbc0ef..7782134 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/shared/stub/system_request_reveal.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#include "starboard/system.h"
 
-#include "starboard/raspi/shared/atomic_public.h"
-
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+void SbSystemRequestReveal() {
+}
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/stub/system_request_stop.cc b/src/starboard/shared/stub/system_request_stop.cc
index 4fef32d..f8c9564 100644
--- a/src/starboard/shared/stub/system_request_stop.cc
+++ b/src/starboard/shared/stub/system_request_stop.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/system.h"
 
-void SbSystemRequestStop(int /*error_level*/) {
-}
+void SbSystemRequestStop(int error_level) {}
diff --git a/src/starboard/shared/stub/system_request_suspend.cc b/src/starboard/shared/stub/system_request_suspend.cc
index 3f39b8b..f717698 100644
--- a/src/starboard/shared/stub/system_request_suspend.cc
+++ b/src/starboard/shared/stub/system_request_suspend.cc
@@ -14,5 +14,9 @@
 
 #include "starboard/system.h"
 
+#if SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION && \
+    !SB_HAS(CONCEALED_STATE)
 void SbSystemRequestSuspend() {
 }
+#endif  // SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION &&
+        // !SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/stub/system_request_unpause.cc b/src/starboard/shared/stub/system_request_unpause.cc
index c36d314..f73550f 100644
--- a/src/starboard/shared/stub/system_request_unpause.cc
+++ b/src/starboard/shared/stub/system_request_unpause.cc
@@ -14,5 +14,9 @@
 
 #include "starboard/system.h"
 
+#if SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION && \
+    !SB_HAS(CONCEALED_STATE)
 void SbSystemRequestUnpause() {
 }
+#endif  // SB_API_VERSION < SB_ADD_CONCEALED_STATE_SUPPORT_VERSION &&
+        // !SB_HAS(CONCEALED_STATE)
diff --git a/src/starboard/shared/stub/system_sort.cc b/src/starboard/shared/stub/system_sort.cc
index e5d7c43..9b71f82 100644
--- a/src/starboard/shared/stub/system_sort.cc
+++ b/src/starboard/shared/stub/system_sort.cc
@@ -14,8 +14,7 @@
 
 #include "starboard/system.h"
 
-void SbSystemSort(void* /*base*/,
-                  size_t /*element_count*/,
-                  size_t /*element_width*/,
-                  SbSystemComparator /*comparator*/) {
-}
+void SbSystemSort(void* base,
+                  size_t element_count,
+                  size_t element_width,
+                  SbSystemComparator comparator) {}
diff --git a/src/starboard/shared/stub/system_symbolize.cc b/src/starboard/shared/stub/system_symbolize.cc
index 383860e..218d5f7 100644
--- a/src/starboard/shared/stub/system_symbolize.cc
+++ b/src/starboard/shared/stub/system_symbolize.cc
@@ -14,7 +14,6 @@
 
 #include "starboard/system.h"
 
-bool SbSystemSymbolize(const void* /*address*/, char* /*out_buffer*/,
-                       int /*buffer_size*/) {
+bool SbSystemSymbolize(const void* address, char* out_buffer, int buffer_size) {
   return false;
 }
diff --git a/src/starboard/shared/stub/thread_context_get_pointer.cc b/src/starboard/shared/stub/thread_context_get_pointer.cc
index 9c7acc2..030a33b 100644
--- a/src/starboard/shared/stub/thread_context_get_pointer.cc
+++ b/src/starboard/shared/stub/thread_context_get_pointer.cc
@@ -18,9 +18,6 @@
 bool SbThreadContextGetPointer(SbThreadContext context,
                                SbThreadContextProperty property,
                                void** out_value) {
-  SB_UNREFERENCED_PARAMETER(context);
-  SB_UNREFERENCED_PARAMETER(property);
-  SB_UNREFERENCED_PARAMETER(out_value);
   return false;
 }
 #endif  // SB_API_VERSION >= 11
diff --git a/src/starboard/shared/stub/thread_create.cc b/src/starboard/shared/stub/thread_create.cc
index ab57f75..7dc0360 100644
--- a/src/starboard/shared/stub/thread_create.cc
+++ b/src/starboard/shared/stub/thread_create.cc
@@ -14,12 +14,12 @@
 
 #include "starboard/thread.h"
 
-SbThread SbThreadCreate(int64_t /*stack_size*/,
-                        SbThreadPriority /*priority*/,
-                        SbThreadAffinity /*affinity*/,
-                        bool /*joinable*/,
-                        const char* /*name*/,
-                        SbThreadEntryPoint /*entry_point*/,
-                        void* /*context*/) {
+SbThread SbThreadCreate(int64_t stack_size,
+                        SbThreadPriority priority,
+                        SbThreadAffinity affinity,
+                        bool joinable,
+                        const char* name,
+                        SbThreadEntryPoint entry_point,
+                        void* context) {
   return kSbThreadInvalid;
 }
diff --git a/src/starboard/shared/stub/thread_create_local_key.cc b/src/starboard/shared/stub/thread_create_local_key.cc
index 7e00082..6974ccb 100644
--- a/src/starboard/shared/stub/thread_create_local_key.cc
+++ b/src/starboard/shared/stub/thread_create_local_key.cc
@@ -14,7 +14,6 @@
 
 #include "starboard/thread.h"
 
-SbThreadLocalKey SbThreadCreateLocalKey(
-    SbThreadLocalDestructor /*destructor*/) {
+SbThreadLocalKey SbThreadCreateLocalKey(SbThreadLocalDestructor destructor) {
   return kSbThreadLocalKeyInvalid;
 }
diff --git a/src/starboard/shared/stub/thread_create_priority.cc b/src/starboard/shared/stub/thread_create_priority.cc
index c003edb..9266844 100644
--- a/src/starboard/shared/stub/thread_create_priority.cc
+++ b/src/starboard/shared/stub/thread_create_priority.cc
@@ -18,12 +18,12 @@
 namespace shared {
 namespace pthread {
 
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#if SB_API_VERSION >= 12
 
 // Default implementation without thread priority support
-void ThreadSetPriority(SbThreadPriority /* priority */) {}
+void ThreadSetPriority(SbThreadPriority priority) {}
 
-#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+#endif  // SB_API_VERSION >= 12
 
 }  // namespace pthread
 }  // namespace shared
diff --git a/src/starboard/shared/stub/thread_destroy_local_key.cc b/src/starboard/shared/stub/thread_destroy_local_key.cc
index eb7ddc9..f5e3655 100644
--- a/src/starboard/shared/stub/thread_destroy_local_key.cc
+++ b/src/starboard/shared/stub/thread_destroy_local_key.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/thread.h"
 
-void SbThreadDestroyLocalKey(SbThreadLocalKey /*key*/) {
-}
+void SbThreadDestroyLocalKey(SbThreadLocalKey key) {}
diff --git a/src/starboard/shared/stub/thread_detach.cc b/src/starboard/shared/stub/thread_detach.cc
index 1fb5b34..b54ecd9 100644
--- a/src/starboard/shared/stub/thread_detach.cc
+++ b/src/starboard/shared/stub/thread_detach.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/thread.h"
 
-void SbThreadDetach(SbThread /*thread*/) {
-}
+void SbThreadDetach(SbThread thread) {}
diff --git a/src/starboard/shared/stub/thread_get_local_value.cc b/src/starboard/shared/stub/thread_get_local_value.cc
index 0057ff3..103c5be 100644
--- a/src/starboard/shared/stub/thread_get_local_value.cc
+++ b/src/starboard/shared/stub/thread_get_local_value.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/thread.h"
 
-void* SbThreadGetLocalValue(SbThreadLocalKey /*key*/) {
+void* SbThreadGetLocalValue(SbThreadLocalKey key) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/thread_get_name.cc b/src/starboard/shared/stub/thread_get_name.cc
index 2dbcd22..3ea652c 100644
--- a/src/starboard/shared/stub/thread_get_name.cc
+++ b/src/starboard/shared/stub/thread_get_name.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/thread.h"
 
-void SbThreadGetName(char* /*buffer*/, int /*buffer_size*/) {
-}
+void SbThreadGetName(char* buffer, int buffer_size) {}
diff --git a/src/starboard/shared/stub/thread_is_equal.cc b/src/starboard/shared/stub/thread_is_equal.cc
index 9290650..fa89469 100644
--- a/src/starboard/shared/stub/thread_is_equal.cc
+++ b/src/starboard/shared/stub/thread_is_equal.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/thread.h"
 
-bool SbThreadIsEqual(SbThread /*thread1*/, SbThread /*thread2*/) {
+bool SbThreadIsEqual(SbThread thread1, SbThread thread2) {
   return false;
 }
diff --git a/src/starboard/shared/stub/thread_join.cc b/src/starboard/shared/stub/thread_join.cc
index cd6cfcf..54059ec 100644
--- a/src/starboard/shared/stub/thread_join.cc
+++ b/src/starboard/shared/stub/thread_join.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/thread.h"
 
-bool SbThreadJoin(SbThread /*thread*/, void** /*out_return*/) {
+bool SbThreadJoin(SbThread thread, void** out_return) {
   return false;
 }
diff --git a/src/starboard/shared/stub/thread_sampler_create.cc b/src/starboard/shared/stub/thread_sampler_create.cc
index f1f1f01..068f04e 100644
--- a/src/starboard/shared/stub/thread_sampler_create.cc
+++ b/src/starboard/shared/stub/thread_sampler_create.cc
@@ -17,7 +17,6 @@
 
 #if SB_API_VERSION >= 11
 SbThreadSampler SbThreadSamplerCreate(SbThread thread) {
-  SB_UNREFERENCED_PARAMETER(thread);
   SB_NOTIMPLEMENTED() << "Profiling is not supported on this platform.";
   return kSbThreadSamplerInvalid;
 }
diff --git a/src/starboard/shared/stub/thread_sampler_destroy.cc b/src/starboard/shared/stub/thread_sampler_destroy.cc
index 73fcaca..20a0085 100644
--- a/src/starboard/shared/stub/thread_sampler_destroy.cc
+++ b/src/starboard/shared/stub/thread_sampler_destroy.cc
@@ -16,6 +16,5 @@
 
 #if SB_API_VERSION >= 11
 void SbThreadSamplerDestroy(SbThreadSampler sampler) {
-    SB_UNREFERENCED_PARAMETER(sampler);
 }
 #endif  // SB_API_VERSION >= 11
diff --git a/src/starboard/shared/stub/thread_sampler_freeze.cc b/src/starboard/shared/stub/thread_sampler_freeze.cc
index 4bbbafb..d8c0877 100644
--- a/src/starboard/shared/stub/thread_sampler_freeze.cc
+++ b/src/starboard/shared/stub/thread_sampler_freeze.cc
@@ -16,7 +16,6 @@
 
 #if SB_API_VERSION >= 11
 SbThreadContext SbThreadSamplerFreeze(SbThreadSampler sampler) {
-  SB_UNREFERENCED_PARAMETER(sampler);
   return kSbThreadContextInvalid;
 }
 #endif  // SB_API_VERSION >= 11
diff --git a/src/starboard/shared/stub/thread_sampler_thaw.cc b/src/starboard/shared/stub/thread_sampler_thaw.cc
index 9b2efef..4f86479 100644
--- a/src/starboard/shared/stub/thread_sampler_thaw.cc
+++ b/src/starboard/shared/stub/thread_sampler_thaw.cc
@@ -16,7 +16,6 @@
 
 #if SB_API_VERSION >= 11
 bool SbThreadSamplerThaw(SbThreadSampler sampler) {
-  SB_UNREFERENCED_PARAMETER(sampler);
   return false;
 }
 #endif  // SB_API_VERSION >= 11
diff --git a/src/starboard/shared/stub/thread_set_local_value.cc b/src/starboard/shared/stub/thread_set_local_value.cc
index 5ee9205..8288928 100644
--- a/src/starboard/shared/stub/thread_set_local_value.cc
+++ b/src/starboard/shared/stub/thread_set_local_value.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/thread.h"
 
-bool SbThreadSetLocalValue(SbThreadLocalKey /*key*/, void* /*value*/) {
+bool SbThreadSetLocalValue(SbThreadLocalKey key, void* value) {
   return false;
 }
diff --git a/src/starboard/shared/stub/thread_set_name.cc b/src/starboard/shared/stub/thread_set_name.cc
index 45e12bb..b5b4e27 100644
--- a/src/starboard/shared/stub/thread_set_name.cc
+++ b/src/starboard/shared/stub/thread_set_name.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/thread.h"
 
-void SbThreadSetName(const char* /*name*/) {
-}
+void SbThreadSetName(const char* name) {}
diff --git a/src/starboard/shared/stub/thread_sleep.cc b/src/starboard/shared/stub/thread_sleep.cc
index 0754319..49eb0a2 100644
--- a/src/starboard/shared/stub/thread_sleep.cc
+++ b/src/starboard/shared/stub/thread_sleep.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/thread.h"
 
-void SbThreadSleep(SbTime /*duration*/) {
-}
+void SbThreadSleep(SbTime duration) {}
diff --git a/src/starboard/shared/stub/time_is_time_thread_now_supported.cc b/src/starboard/shared/stub/time_is_time_thread_now_supported.cc
index de464dc..63e68f7 100644
--- a/src/starboard/shared/stub/time_is_time_thread_now_supported.cc
+++ b/src/starboard/shared/stub/time_is_time_thread_now_supported.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/time.h"
 
-#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbTimeIsTimeThreadNowSupported() {
   return false;
diff --git a/src/starboard/shared/stub/ui_nav_get_interface.cc b/src/starboard/shared/stub/ui_nav_get_interface.cc
index 3abad10..aff9582 100644
--- a/src/starboard/shared/stub/ui_nav_get_interface.cc
+++ b/src/starboard/shared/stub/ui_nav_get_interface.cc
@@ -14,10 +14,10 @@
 
 #include "starboard/ui_navigation.h"
 
-#if SB_API_VERSION >= SB_UI_NAVIGATION_VERSION
+#if SB_API_VERSION >= 12
 
-bool SbUiNavGetInterface(SbUiNavInterface* /* out_interface */) {
+bool SbUiNavGetInterface(SbUiNavInterface* out_interface) {
   return false;
 }
 
-#endif  // SB_API_VERSION >= SB_UI_NAVIGATION_VERSION
+#endif  // SB_API_VERSION >= 12
diff --git a/src/starboard/shared/stub/user_get_property.cc b/src/starboard/shared/stub/user_get_property.cc
index 22fb519..02d8abb 100644
--- a/src/starboard/shared/stub/user_get_property.cc
+++ b/src/starboard/shared/stub/user_get_property.cc
@@ -14,13 +14,13 @@
 
 #include "starboard/user.h"
 
-int SbUserGetPropertySize(SbUser /*user*/, SbUserPropertyId /*property_id*/) {
+int SbUserGetPropertySize(SbUser user, SbUserPropertyId property_id) {
   return 0;
 }
 
-bool SbUserGetProperty(SbUser /*user*/,
-                       SbUserPropertyId /*property_id*/,
-                       char* /*out_value*/,
-                       int /*value_size*/) {
+bool SbUserGetProperty(SbUser user,
+                       SbUserPropertyId property_id,
+                       char* out_value,
+                       int value_size) {
   return false;
 }
diff --git a/src/starboard/shared/stub/user_get_signed_in.cc b/src/starboard/shared/stub/user_get_signed_in.cc
index 7c3904b..938a816 100644
--- a/src/starboard/shared/stub/user_get_signed_in.cc
+++ b/src/starboard/shared/stub/user_get_signed_in.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/user.h"
 
-int SbUserGetSignedIn(SbUser* /*out_users*/, int /*users_size*/) {
+int SbUserGetSignedIn(SbUser* out_users, int users_size) {
   return 0;
 }
diff --git a/src/starboard/shared/stub/window_blur_on_screen_keyboard.cc b/src/starboard/shared/stub/window_blur_on_screen_keyboard.cc
index f4dbd36..3612354 100644
--- a/src/starboard/shared/stub/window_blur_on_screen_keyboard.cc
+++ b/src/starboard/shared/stub/window_blur_on_screen_keyboard.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
-void SbWindowBlurOnScreenKeyboard(SbWindow /* window */, int /* ticket */) {}
+void SbWindowBlurOnScreenKeyboard(SbWindow window, int ticket) {}
 
 #endif
diff --git a/src/starboard/shared/stub/window_create.cc b/src/starboard/shared/stub/window_create.cc
index 06d79d9..51c8802 100644
--- a/src/starboard/shared/stub/window_create.cc
+++ b/src/starboard/shared/stub/window_create.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/window.h"
 
-SbWindow SbWindowCreate(const SbWindowOptions* /*options*/) {
+SbWindow SbWindowCreate(const SbWindowOptions* options) {
   return kSbWindowInvalid;
 }
diff --git a/src/starboard/shared/stub/window_destroy.cc b/src/starboard/shared/stub/window_destroy.cc
index 050904b..f2ca58e 100644
--- a/src/starboard/shared/stub/window_destroy.cc
+++ b/src/starboard/shared/stub/window_destroy.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/window.h"
 
-bool SbWindowDestroy(SbWindow /*window*/) {
+bool SbWindowDestroy(SbWindow window) {
   return false;
 }
diff --git a/src/starboard/shared/stub/window_focus_on_screen_keyboard.cc b/src/starboard/shared/stub/window_focus_on_screen_keyboard.cc
index 76b9387..81c89fa 100644
--- a/src/starboard/shared/stub/window_focus_on_screen_keyboard.cc
+++ b/src/starboard/shared/stub/window_focus_on_screen_keyboard.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
-void SbWindowFocusOnScreenKeyboard(SbWindow /* window */, int /* ticket */) {}
+void SbWindowFocusOnScreenKeyboard(SbWindow window, int ticket) {}
 
 #endif
diff --git a/src/starboard/shared/stub/window_get_diagonal_size_in_inches.cc b/src/starboard/shared/stub/window_get_diagonal_size_in_inches.cc
index e403c38..159dfce 100644
--- a/src/starboard/shared/stub/window_get_diagonal_size_in_inches.cc
+++ b/src/starboard/shared/stub/window_get_diagonal_size_in_inches.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/window.h"
 
-float SbWindowGetDiagonalSizeInInches(SbWindow /*window*/) {
+float SbWindowGetDiagonalSizeInInches(SbWindow window) {
   // 0 is a signal meaning that the platform doesn't know the diagonal screen
   // length.
   return 0.f;
diff --git a/src/starboard/shared/stub/window_get_on_screen_keyboard_bounding_rect.cc b/src/starboard/shared/stub/window_get_on_screen_keyboard_bounding_rect.cc
index 8072dbd..b6001a5 100644
--- a/src/starboard/shared/stub/window_get_on_screen_keyboard_bounding_rect.cc
+++ b/src/starboard/shared/stub/window_get_on_screen_keyboard_bounding_rect.cc
@@ -14,11 +14,10 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
-bool SbWindowGetOnScreenKeyboardBoundingRect(
-    SbWindow /* window */,
-    SbWindowRect* /* bounding_rect */) {
+bool SbWindowGetOnScreenKeyboardBoundingRect(SbWindow window,
+                                             SbWindowRect* bounding_rect) {
   return false;
 }
 
diff --git a/src/starboard/shared/stub/window_get_platform_handle.cc b/src/starboard/shared/stub/window_get_platform_handle.cc
index 1463445..c3a55b5 100644
--- a/src/starboard/shared/stub/window_get_platform_handle.cc
+++ b/src/starboard/shared/stub/window_get_platform_handle.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/window.h"
 
-void* SbWindowGetPlatformHandle(SbWindow /*window*/) {
+void* SbWindowGetPlatformHandle(SbWindow window) {
   return NULL;
 }
diff --git a/src/starboard/shared/stub/window_get_size.cc b/src/starboard/shared/stub/window_get_size.cc
index c5c3829..a6a6396 100644
--- a/src/starboard/shared/stub/window_get_size.cc
+++ b/src/starboard/shared/stub/window_get_size.cc
@@ -14,6 +14,6 @@
 
 #include "starboard/window.h"
 
-bool SbWindowGetSize(SbWindow /*window*/, SbWindowSize* /*size*/) {
+bool SbWindowGetSize(SbWindow window, SbWindowSize* size) {
   return false;
 }
diff --git a/src/starboard/shared/stub/window_hide_on_screen_keyboard.cc b/src/starboard/shared/stub/window_hide_on_screen_keyboard.cc
index 2632582..8f8468c 100644
--- a/src/starboard/shared/stub/window_hide_on_screen_keyboard.cc
+++ b/src/starboard/shared/stub/window_hide_on_screen_keyboard.cc
@@ -14,8 +14,8 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
-void SbWindowHideOnScreenKeyboard(SbWindow /* window */, int /* ticket */) {}
+void SbWindowHideOnScreenKeyboard(SbWindow window, int ticket) {}
 
 #endif
diff --git a/src/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc b/src/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc
index efc823b..7d7d735 100644
--- a/src/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc
+++ b/src/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc
@@ -14,9 +14,9 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
-bool SbWindowIsOnScreenKeyboardShown(SbWindow /* window */) {
+bool SbWindowIsOnScreenKeyboardShown(SbWindow window) {
   return false;
 }
 
diff --git a/src/starboard/shared/stub/window_on_screen_keyboard_is_supported.cc b/src/starboard/shared/stub/window_on_screen_keyboard_is_supported.cc
index b9eb7e8..ab63af8 100644
--- a/src/starboard/shared/stub/window_on_screen_keyboard_is_supported.cc
+++ b/src/starboard/shared/stub/window_on_screen_keyboard_is_supported.cc
@@ -14,7 +14,7 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
 bool SbWindowOnScreenKeyboardIsSupported() {
   return false;
diff --git a/src/starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc b/src/starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc
index 94c75b1..2fdd5a4 100644
--- a/src/starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc
+++ b/src/starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc
@@ -14,12 +14,11 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 #if SB_API_VERSION >= 11
 bool SbWindowOnScreenKeyboardSuggestionsSupported(SbWindow window) {
   return false;
 }
 #endif  // SB_API_VERSION >= 11
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/shared/stub/window_set_default_options.cc b/src/starboard/shared/stub/window_set_default_options.cc
index 6ea054a..b6b7222 100644
--- a/src/starboard/shared/stub/window_set_default_options.cc
+++ b/src/starboard/shared/stub/window_set_default_options.cc
@@ -14,5 +14,4 @@
 
 #include "starboard/window.h"
 
-void SbWindowSetDefaultOptions(SbWindowOptions* /*options*/) {
-}
+void SbWindowSetDefaultOptions(SbWindowOptions* options) {}
diff --git a/src/starboard/shared/stub/window_set_on_screen_keyboard_keep_focus.cc b/src/starboard/shared/stub/window_set_on_screen_keyboard_keep_focus.cc
index ef192f6..13afa89 100644
--- a/src/starboard/shared/stub/window_set_on_screen_keyboard_keep_focus.cc
+++ b/src/starboard/shared/stub/window_set_on_screen_keyboard_keep_focus.cc
@@ -14,9 +14,8 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
-void SbWindowSetOnScreenKeyboardKeepFocus(SbWindow /* window */,
-                                          bool /* keep_focus */) {}
+void SbWindowSetOnScreenKeyboardKeepFocus(SbWindow window, bool keep_focus) {}
 
 #endif
diff --git a/src/starboard/shared/stub/window_show_on_screen_keyboard.cc b/src/starboard/shared/stub/window_show_on_screen_keyboard.cc
index aa17235..775aa76 100644
--- a/src/starboard/shared/stub/window_show_on_screen_keyboard.cc
+++ b/src/starboard/shared/stub/window_show_on_screen_keyboard.cc
@@ -14,10 +14,10 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 
-void SbWindowShowOnScreenKeyboard(SbWindow /* window */,
-                                  const char* /* input_text */,
-                                  int /* ticket */) {}
+void SbWindowShowOnScreenKeyboard(SbWindow window,
+                                  const char* input_text,
+                                  int ticket) {}
 
 #endif
diff --git a/src/starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc b/src/starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc
index 665ba4e..dd91827 100644
--- a/src/starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc
+++ b/src/starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc
@@ -14,13 +14,12 @@
 
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 #if SB_API_VERSION >= 11
 void SbWindowUpdateOnScreenKeyboardSuggestions(SbWindow window,
                                                const char* suggestions[],
                                                int num_suggestions,
                                                int ticket) {}
 #endif  // SB_API_VERSION >= 11
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/shared/widevine/drm_system_widevine.cc b/src/starboard/shared/widevine/drm_system_widevine.cc
index fb6b48e..2dd57ff 100644
--- a/src/starboard/shared/widevine/drm_system_widevine.cc
+++ b/src/starboard/shared/widevine/drm_system_widevine.cc
@@ -401,11 +401,11 @@
   input.iv_length = static_cast<uint32_t>(initialization_vector.size());
   input.is_video = (buffer->sample_type() == kSbMediaTypeVideo);
 
-#if SB_API_VERSION >= SB_DRM_CBCS_SUPPORT_VERSION
+#if SB_API_VERSION >= 12
   input.pattern.encrypted_blocks =
       drm_info->encryption_pattern.crypt_byte_block;
   input.pattern.clear_blocks = drm_info->encryption_pattern.skip_byte_block;
-#endif  // SB_API_VERSION >= SB_DRM_CBCS_SUPPORT_VERSION
+#endif  // SB_API_VERSION >= 12
 
   std::vector<uint8_t> output_data(buffer->size());
   wv3cdm::OutputBuffer output;
@@ -447,13 +447,13 @@
     if (subsample.encrypted_byte_count) {
       input.last_subsample = i + 1 == buffer->drm_info()->subsample_count;
       input.encryption_scheme = wv3cdm::EncryptionScheme::kAesCtr;
-#if SB_API_VERSION >= SB_DRM_CBCS_SUPPORT_VERSION
+#if SB_API_VERSION >= 12
       if (drm_info->encryption_scheme == kSbDrmEncryptionSchemeAesCbc) {
         input.encryption_scheme = wv3cdm::EncryptionScheme::kAesCbc;
       } else {
         SB_DCHECK(drm_info->encryption_scheme == kSbDrmEncryptionSchemeAesCtr);
       }
-#endif  // SB_API_VERSION >= SB_DRM_CBCS_SUPPORT_VERSION
+#endif  // SB_API_VERSION >= 12
       input.data_length = subsample.encrypted_byte_count;
 
       wv3cdm::Status status = cdm_->decrypt(input, output);
@@ -631,14 +631,11 @@
 }
 
 void DrmSystemWidevine::onRemoveComplete(const std::string& wvcdm_session_id) {
-  SB_UNREFERENCED_PARAMETER(wvcdm_session_id);
   SB_NOTIMPLEMENTED();
 }
 
 void DrmSystemWidevine::onDeferredComplete(const std::string& wvcdm_session_id,
                                            wv3cdm::Status result) {
-  SB_UNREFERENCED_PARAMETER(wvcdm_session_id);
-  SB_UNREFERENCED_PARAMETER(result);
   SB_NOTIMPLEMENTED();
 }
 
diff --git a/src/starboard/shared/widevine/drm_system_widevine.h b/src/starboard/shared/widevine/drm_system_widevine.h
index c1a66a9..a12b7c1 100644
--- a/src/starboard/shared/widevine/drm_system_widevine.h
+++ b/src/starboard/shared/widevine/drm_system_widevine.h
@@ -85,6 +85,8 @@
                                const void* certificate,
                                int certificate_size) override;
 
+  const void* GetMetrics(int* size) override { return NULL; }
+
  private:
   // Stores the data necessary to call GenerateSessionUpdateRequestInternal().
   struct GenerateSessionUpdateRequestData {
diff --git a/src/starboard/shared/widevine/media_is_supported.cc b/src/starboard/shared/widevine/media_is_supported.cc
index 55292ab..2c5afbb 100644
--- a/src/starboard/shared/widevine/media_is_supported.cc
+++ b/src/starboard/shared/widevine/media_is_supported.cc
@@ -20,8 +20,5 @@
                         const char* key_system) {
   using starboard::shared::widevine::DrmSystemWidevine;
 
-  SB_UNREFERENCED_PARAMETER(video_codec);
-  SB_UNREFERENCED_PARAMETER(audio_codec);
-
   return DrmSystemWidevine::IsKeySystemSupported(key_system);
 }
diff --git a/src/starboard/shared/x11/application_x11.cc b/src/starboard/shared/x11/application_x11.cc
index 07cfc1f..594639b 100644
--- a/src/starboard/shared/x11/application_x11.cc
+++ b/src/starboard/shared/x11/application_x11.cc
@@ -694,6 +694,11 @@
 ApplicationX11::ApplicationX11()
     : wake_up_atom_(None),
       wm_delete_atom_(None),
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+      wm_change_state_atom_(None),
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
       composite_event_id_(kSbEventIdInvalid),
       display_(NULL),
       paste_buffer_key_release_pending_(false) {
@@ -949,6 +954,11 @@
 
   wake_up_atom_ = XInternAtom(display_, "WakeUpAtom", 0);
   wm_delete_atom_ = XInternAtom(display_, "WM_DELETE_WINDOW", True);
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+  wm_change_state_atom_ = XInternAtom(display_, "WM_CHANGE_STATE", True);
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
 
   Composite();
 
@@ -967,6 +977,11 @@
   display_ = NULL;
   wake_up_atom_ = None;
   wm_delete_atom_ = None;
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+  wm_change_state_atom_ = None;
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
 }
 
 shared::starboard::Application::Event* ApplicationX11::GetPendingEvent() {
@@ -1179,6 +1194,22 @@
         Stop(0);
         return NULL;
       }
+
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+      if (client_message->message_type == wm_change_state_atom_) {
+        SB_DLOG(INFO) << "Received WM_CHANGE_STATE message.";
+        if (x_event->xclient.data.l[0] == IconicState) {
+          Reveal(NULL, NULL);
+          return NULL;
+        } else if (x_event->xclient.data.l[0] == NormalState) {
+          Conceal(NULL, NULL);
+          return NULL;
+        }
+      }
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
+
       // Unknown event, ignore.
       return NULL;
     }
@@ -1276,6 +1307,17 @@
       return new Event(kSbEventTypeInput, data.release(),
                        &DeleteDestructor<SbInputData>);
     }
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+    case FocusIn: {
+      Focus(NULL, NULL);
+      return NULL;
+    }
+    case FocusOut: {
+      Blur(NULL, NULL);
+      return NULL;
+    }
+#else
     case FocusIn: {
       Unpause(NULL, NULL);
       return NULL;
@@ -1284,6 +1326,8 @@
       Pause(NULL, NULL);
       return NULL;
     }
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
     case ConfigureNotify: {
 #if SB_API_VERSION >= 8
       XConfigureEvent* x_configure_event =
diff --git a/src/starboard/shared/x11/application_x11.h b/src/starboard/shared/x11/application_x11.h
index e63cd91..75934d3 100644
--- a/src/starboard/shared/x11/application_x11.h
+++ b/src/starboard/shared/x11/application_x11.h
@@ -122,6 +122,11 @@
 
   Atom wake_up_atom_;
   Atom wm_delete_atom_;
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+  Atom wm_change_state_atom_;
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
 
   SbEventId composite_event_id_;
   Mutex frame_mutex_;
diff --git a/src/starboard/socket.h b/src/starboard/socket.h
index 663c43b..adc3661 100644
--- a/src/starboard/socket.h
+++ b/src/starboard/socket.h
@@ -135,7 +135,7 @@
   return socket != kSbSocketInvalid;
 }
 
-#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 // Returns whether IPV6 is supported on the current platform.
 SB_EXPORT bool SbSocketIsIpv6Supported();
 #endif
diff --git a/src/starboard/speech_recognizer.h b/src/starboard/speech_recognizer.h
index 4524a84..a34eaa6 100644
--- a/src/starboard/speech_recognizer.h
+++ b/src/starboard/speech_recognizer.h
@@ -35,8 +35,7 @@
 #include "starboard/export.h"
 #include "starboard/types.h"
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
 
 #ifdef __cplusplus
 extern "C" {
@@ -146,7 +145,7 @@
   void* context;
 };
 
-#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 // Returns whether the platform supports SbSpeechRecognizer.
 SB_EXPORT bool SbSpeechRecognizerIsSupported();
 #endif
@@ -200,7 +199,7 @@
 }  // extern "C"
 #endif
 
-#endif  // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_RECOGNIZER)
         // && SB_API_VERSION >= 5
 
diff --git a/src/starboard/speech_synthesis.h b/src/starboard/speech_synthesis.h
index 771be95..bee3246 100644
--- a/src/starboard/speech_synthesis.h
+++ b/src/starboard/speech_synthesis.h
@@ -29,14 +29,13 @@
 #include "starboard/export.h"
 #include "starboard/types.h"
 
-#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \
-    SB_HAS(SPEECH_SYNTHESIS)
+#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_SYNTHESIS)
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 // Returns whether the platform supports speech synthesis
 SB_EXPORT bool SbSpeechSynthesisIsSupported();
 #endif
@@ -60,7 +59,7 @@
 }  // extern "C"
 #endif
 
-#endif  // SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(SPEECH_SYNTHESIS)
 
 #endif  // STARBOARD_SPEECH_SYNTHESIS_H_
diff --git a/src/starboard/stub/BUILD.gn b/src/starboard/stub/BUILD.gn
index adda976..3e17161 100644
--- a/src/starboard/stub/BUILD.gn
+++ b/src/starboard/stub/BUILD.gn
@@ -216,6 +216,7 @@
     "//starboard/shared/stub/drm_create_system.cc",
     "//starboard/shared/stub/drm_destroy_system.cc",
     "//starboard/shared/stub/drm_generate_session_update_request.cc",
+    "//starboard/shared/stub/drm_get_metrics.cc",
     "//starboard/shared/stub/drm_is_server_certificate_updatable.cc",
     "//starboard/shared/stub/drm_system_internal.h",
     "//starboard/shared/stub/drm_update_server_certificate.cc",
diff --git a/src/starboard/stub/application_stub.cc b/src/starboard/stub/application_stub.cc
index 5600438..5b8dee5 100644
--- a/src/starboard/stub/application_stub.cc
+++ b/src/starboard/stub/application_stub.cc
@@ -42,7 +42,6 @@
 
 shared::starboard::Application::Event*
 ApplicationStub::WaitForSystemEventWithTimeout(SbTime time) {
-  SB_UNREFERENCED_PARAMETER(time);
   return NULL;
 }
 
diff --git a/src/starboard/stub/configuration.cc b/src/starboard/stub/configuration.cc
new file mode 100644
index 0000000..d438884
--- /dev/null
+++ b/src/starboard/stub/configuration.cc
@@ -0,0 +1,67 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/stub/configuration.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/configuration_defaults.h"
+
+namespace starboard {
+namespace stub {
+
+namespace {
+
+const char* CobaltRasterizerType() {
+  return "stub";
+}
+
+bool CobaltEnableJit() {
+  return true;
+}
+
+const CobaltExtensionConfigurationApi kConfigurationApi = {
+    kCobaltExtensionConfigurationName,
+    1,
+    &common::CobaltUserOnExitStrategyDefault,
+    &common::CobaltRenderDirtyRegionOnlyDefault,
+    &common::CobaltEglSwapIntervalDefault,
+    &common::CobaltFallbackSplashScreenUrlDefault,
+    &common::CobaltEnableQuicDefault,
+    &common::CobaltSkiaCacheSizeInBytesDefault,
+    &common::CobaltOffscreenTargetCacheSizeInBytesDefault,
+    &common::CobaltEncodedImageCacheSizeInBytesDefault,
+    &common::CobaltImageCacheSizeInBytesDefault,
+    &common::CobaltLocalTypefaceCacheSizeInBytesDefault,
+    &common::CobaltRemoteTypefaceCacheSizeInBytesDefault,
+    &common::CobaltMeshCacheSizeInBytesDefault,
+    &common::CobaltSoftwareSurfaceCacheSizeInBytesDefault,
+    &common::CobaltImageCacheCapacityMultiplierWhenPlayingVideoDefault,
+    &common::CobaltSkiaGlyphAtlasWidthDefault,
+    &common::CobaltSkiaGlyphAtlasHeightDefault,
+    &common::CobaltJsGarbageCollectionThresholdInBytesDefault,
+    &common::CobaltReduceCpuMemoryByDefault,
+    &common::CobaltReduceGpuMemoryByDefault,
+    &common::CobaltGcZealDefault,
+    &CobaltRasterizerType,
+    &CobaltEnableJit,
+};
+
+}  // namespace
+
+const void* GetConfigurationApi() {
+  return &kConfigurationApi;
+}
+
+}  // namespace stub
+}  // namespace starboard
diff --git a/src/starboard/stub/configuration.gni b/src/starboard/stub/configuration.gni
index 77d2f4b..9babbcb 100644
--- a/src/starboard/stub/configuration.gni
+++ b/src/starboard/stub/configuration.gni
@@ -12,9 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Use a stub rasterizer and graphical setup
-rasterizer_type = "stub"
-
 # No GL drivers available
 gl_type = "none"
 
diff --git a/src/starboard/raspi/0/atomic_public.h b/src/starboard/stub/configuration.h
similarity index 64%
copy from src/starboard/raspi/0/atomic_public.h
copy to src/starboard/stub/configuration.h
index 0fbc0ef..d02d27d 100644
--- a/src/starboard/raspi/0/atomic_public.h
+++ b/src/starboard/stub/configuration.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_STUB_CONFIGURATION_H_
+#define STARBOARD_STUB_CONFIGURATION_H_
 
-#include "starboard/raspi/shared/atomic_public.h"
+namespace starboard {
+namespace stub {
 
-#endif  // STARBOARD_RASPI_0_ATOMIC_PUBLIC_H_
+const void* GetConfigurationApi();
+
+}  // namespace stub
+}  // namespace starboard
+
+#endif  // STARBOARD_STUB_CONFIGURATION_H_
diff --git a/src/starboard/stub/configuration_constants.cc b/src/starboard/stub/configuration_constants.cc
index ae91a87..c3e1c74 100644
--- a/src/starboard/stub/configuration_constants.cc
+++ b/src/starboard/stub/configuration_constants.cc
@@ -52,9 +52,6 @@
 // Allow ac3 and ec3 support
 const bool kSbHasAc3Audio = true;
 
-// Specifies whether this platform updates audio frames asynchronously.
-const bool kSbHasAsyncAudioFramesReporting = false;
-
 // Specifies whether this platform has webm/vp9 support.  This should be set to
 // non-zero on platforms with webm/vp9 support.
 const bool kSbHasMediaWebmVp9Support = false;
diff --git a/src/starboard/stub/configuration_public.h b/src/starboard/stub/configuration_public.h
index c339a86..d01541c 100644
--- a/src/starboard/stub/configuration_public.h
+++ b/src/starboard/stub/configuration_public.h
@@ -215,10 +215,6 @@
 
 #define SB_HAS_VIRTUAL_REALITY 1
 
-#ifndef COBALT_FORCE_STUB_RASTERIZER
-#define COBALT_FORCE_STUB_RASTERIZER 1
-#endif
-
 // --- I/O Configuration -----------------------------------------------------
 
 // Whether the current platform implements the on screen keyboard interface.
@@ -255,7 +251,7 @@
 
 // Whether this platform has and should use an MMAP function to map physical
 // memory to the virtual address space.
-#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#if SB_API_VERSION < 12
 #define SB_HAS_MMAP 1
 #endif
 
diff --git a/src/starboard/stub/gyp_configuration.py b/src/starboard/stub/gyp_configuration.py
index 38b5493..2d97119 100644
--- a/src/starboard/stub/gyp_configuration.py
+++ b/src/starboard/stub/gyp_configuration.py
@@ -16,10 +16,16 @@
 import logging
 
 import config.base
-from starboard.build import clang
+from starboard.build import clang as clang_specification
 from starboard.tools import build
+from starboard.tools.toolchain import ar
+from starboard.tools.toolchain import bash
+from starboard.tools.toolchain import clang
+from starboard.tools.toolchain import clangxx
+from starboard.tools.toolchain import cp
+from starboard.tools.toolchain import touch
 
-_SABI_JSON_PATH = 'starboard/sabi/x64/sysv/sabi.json'
+_SABI_JSON_PATH = 'starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json'
 
 
 def CreatePlatformConfig():
@@ -41,7 +47,6 @@
         configuration, use_clang=1)
     variables.update({
         'javascript_engine': 'v8',
-        'cobalt_enable_jit': 1,
     })
     return variables
 
@@ -49,7 +54,7 @@
     if not hasattr(self, 'host_compiler_environment'):
       goma_supports_compiler = True
       self.host_compiler_environment = build.GetHostCompilerEnvironment(
-          clang.GetClangSpecification(), goma_supports_compiler)
+          clang_specification.GetClangSpecification(), goma_supports_compiler)
 
     env_variables = self.host_compiler_environment
     env_variables.update({
@@ -58,6 +63,42 @@
     })
     return env_variables
 
+  def GetTargetToolchain(self, **kwargs):
+    environment_variables = self.GetEnvironmentVariables()
+    cc_path = environment_variables['CC']
+    cxx_path = environment_variables['CXX']
+
+    return [
+        clang.CCompiler(path=cc_path),
+        clang.CxxCompiler(path=cxx_path),
+        clang.AssemblerWithCPreprocessor(path=cc_path),
+        ar.StaticThinLinker(),
+        ar.StaticLinker(),
+        clangxx.ExecutableLinker(path=cxx_path, write_group=True),
+        clangxx.SharedLibraryLinker(path=cxx_path),
+        cp.Copy(),
+        touch.Stamp(),
+        bash.Shell(),
+    ]
+
+  def GetHostToolchain(self, **kwargs):
+    environment_variables = self.GetEnvironmentVariables()
+    cc_path = environment_variables['CC_host']
+    cxx_path = environment_variables['CXX_host']
+
+    return [
+        clang.CCompiler(path=cc_path),
+        clang.CxxCompiler(path=cxx_path),
+        clang.AssemblerWithCPreprocessor(path=cc_path),
+        ar.StaticThinLinker(),
+        ar.StaticLinker(),
+        clangxx.ExecutableLinker(path=cxx_path, write_group=True),
+        clangxx.SharedLibraryLinker(path=cxx_path),
+        cp.Copy(),
+        touch.Stamp(),
+        bash.Shell(),
+    ]
+
   def GetTestFilters(self):
     """Gets all tests to be excluded from a unit test run.
 
diff --git a/src/starboard/stub/starboard_platform.gyp b/src/starboard/stub/starboard_platform.gyp
index 5baf0ca..bb8578d 100644
--- a/src/starboard/stub/starboard_platform.gyp
+++ b/src/starboard/stub/starboard_platform.gyp
@@ -24,8 +24,11 @@
         'application_stub.cc',
         'application_stub.h',
         'atomic_public.h',
+        'configuration.cc',
+        'configuration.h',
         'configuration_constants.cc',
         'main.cc',
+        'system_get_extensions.cc',
         'thread_types_public.h',
         # Include private stubs, if present.
         '<!@(python "<(DEPTH)/starboard/tools/find_private_files.py" "<(DEPTH)" "shared/stub/*.cc")',
diff --git a/src/starboard/stub/stub_sources.gypi b/src/starboard/stub/stub_sources.gypi
index 58b5737..890edd6 100644
--- a/src/starboard/stub/stub_sources.gypi
+++ b/src/starboard/stub/stub_sources.gypi
@@ -20,6 +20,7 @@
         '<(DEPTH)/starboard/shared/starboard/event_cancel.cc',
         '<(DEPTH)/starboard/shared/starboard/event_schedule.cc',
         '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc',
+        '<(DEPTH)/starboard/shared/starboard/memory.cc',
         '<(DEPTH)/starboard/shared/starboard/queue_application.cc',
         '<(DEPTH)/starboard/shared/stub/accessibility_get_caption_settings.cc',
         '<(DEPTH)/starboard/shared/stub/accessibility_get_display_settings.cc',
@@ -71,6 +72,7 @@
         '<(DEPTH)/starboard/shared/stub/drm_create_system.cc',
         '<(DEPTH)/starboard/shared/stub/drm_destroy_system.cc',
         '<(DEPTH)/starboard/shared/stub/drm_generate_session_update_request.cc',
+        '<(DEPTH)/starboard/shared/stub/drm_get_metrics.cc',
         '<(DEPTH)/starboard/shared/stub/drm_is_server_certificate_updatable.cc',
         '<(DEPTH)/starboard/shared/stub/drm_system_internal.h',
         '<(DEPTH)/starboard/shared/stub/drm_update_server_certificate.cc',
@@ -236,7 +238,6 @@
         '<(DEPTH)/starboard/shared/stub/system_get_connection_type.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_device_type.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_error_string.cc',
-        '<(DEPTH)/starboard/shared/stub/system_get_extensions.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_last_error.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_locale_id.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_number_of_processors.cc',
@@ -254,7 +255,12 @@
         '<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc',
         '<(DEPTH)/starboard/shared/stub/system_is_debugger_attached.cc',
         '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_blur.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_conceal.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_focus.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_freeze.cc',
         '<(DEPTH)/starboard/shared/stub/system_request_pause.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_reveal.cc',
         '<(DEPTH)/starboard/shared/stub/system_request_stop.cc',
         '<(DEPTH)/starboard/shared/stub/system_request_suspend.cc',
         '<(DEPTH)/starboard/shared/stub/system_request_unpause.cc',
diff --git a/src/starboard/stub/system_get_extensions.cc b/src/starboard/stub/system_get_extensions.cc
new file mode 100644
index 0000000..31f44f7
--- /dev/null
+++ b/src/starboard/stub/system_get_extensions.cc
@@ -0,0 +1,26 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/string.h"
+#include "starboard/stub/configuration.h"
+
+const void* SbSystemGetExtension(const char* name) {
+  if (SbStringCompareAll(name, kCobaltExtensionConfigurationName) == 0) {
+    return starboard::stub::GetConfigurationApi();
+  }
+  return NULL;
+}
diff --git a/src/starboard/system.h b/src/starboard/system.h
index cc09fb5..b0c19db 100644
--- a/src/starboard/system.h
+++ b/src/starboard/system.h
@@ -64,7 +64,7 @@
   // Full path to the executable file.
   kSbSystemPathExecutableFile,
 
-#if SB_API_VERSION >= SB_STORAGE_PATH_VERSION
+#if SB_API_VERSION >= 12
   // Path to a directory for permanent file storage. Both read and write
   // access is required. This is where an app may store its persistent settings.
   // The location should be user agnostic if possible.
@@ -495,6 +495,68 @@
                                  char* out_buffer,
                                  int buffer_size);
 
+#if SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION || \
+    SB_HAS(CONCEALED_STATE)
+// Requests that the application move into the Blurred state at the next
+// convenient point. This should roughly correspond to "unfocused application"
+// in a traditional window manager, where the application may be partially
+// visible.
+//
+// This function eventually causes a |kSbEventTypeBlur| event to be dispatched
+// to the application. Before the |kSbEventTypeBlur| event is dispatched, some
+// work may continue to be done, and unrelated system events may be dispatched.
+SB_EXPORT void SbSystemRequestBlur();
+
+// Requests that the application move into the Started state at the next
+// convenient point. This should roughly correspond to a "focused application"
+// in a traditional window manager, where the application is fully visible and
+// the primary receiver of input events.
+//
+// This function eventually causes a |kSbEventTypeFocus| event to be
+// dispatched to the application. Before |kSbEventTypeFocus| is dispatched,
+// some work may continue to be done, and unrelated system events may be
+// dispatched.
+SB_EXPORT void SbSystemRequestFocus();
+
+// Requests that the application move into the Concealed state at the next
+// convenient point. This should roughly correspond to "minimization" in a
+// traditional window manager, where the application is no longer visible.
+// However, the background tasks can still be running.
+//
+// This function eventually causes a |kSbEventTypeConceal| event to be
+// dispatched to the application. Before the |kSbEventTypeConceal| event is
+// dispatched, some work may continue to be done, and unrelated system events
+// may be dispatched.
+//
+// In the Concealed state, the application will be invisible, but probably
+// still be running background tasks. The expectation is that an external
+// system event will bring the application out of the Concealed state.
+SB_EXPORT void SbSystemRequestConceal();
+
+// Requests that the application move into the Blurred state at the next
+// convenient point. This should roughly correspond to a "focused application"
+// in a traditional window manager, where the application is fully visible and
+// the primary receiver of input events.
+//
+// This function eventually causes a |kSbEventTypeReveal| event to be
+// dispatched to the application. Before the |kSbEventTypeReveal| event is
+// dispatched, some work may continue to be done, and unrelated system events
+// may be dispatched.
+SB_EXPORT void SbSystemRequestReveal();
+
+// Requests that the application move into the Frozen state at the next
+// convenient point.
+//
+// This function eventually causes a |kSbEventTypeFreeze| event to be
+// dispatched to the application. Before the |kSbEventTypeSuspend| event is
+// dispatched, some work may continue to be done, and unrelated system events
+// may be dispatched.
+//
+// In the Frozen state, the application will be resident, but probably not
+// running. The expectation is that an external system event will bring the
+// application out of the Frozen state.
+SB_EXPORT void SbSystemRequestFreeze();
+#else
 // Requests that the application move into the Paused state at the next
 // convenient point. This should roughly correspond to "unfocused application"
 // in a traditional window manager, where the application may be partially
@@ -529,6 +591,8 @@
 // running. The expectation is that an external system event will bring the
 // application out of the Suspended state.
 SB_EXPORT void SbSystemRequestSuspend();
+#endif  // SB_API_VERSION >= SB_ADD_CONCEALED_STATE_SUPPORT_VERSION ||
+        // SB_HAS(CONCEALED_STATE)
 
 // Requests that the application be terminated gracefully at the next
 // convenient point. In the meantime, some work may continue to be done, and
diff --git a/src/starboard/testing/fake_graphics_context_provider.cc b/src/starboard/testing/fake_graphics_context_provider.cc
index 5a851cf..7a36ae9 100644
--- a/src/starboard/testing/fake_graphics_context_provider.cc
+++ b/src/starboard/testing/fake_graphics_context_provider.cc
@@ -237,7 +237,7 @@
   EGLint context_attrib_list[] = {
       EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE,
   };
-#if SB_API_VERSION < SB_GLES3_DEPRECATED_VERSION && defined(GLES3_SUPPORTED)
+#if SB_API_VERSION < 12 && defined(GLES3_SUPPORTED)
   // Attempt to create an OpenGL ES 3.0 context.
   context_ = EGL_CALL_SIMPLE(eglCreateContext(
       display_, config, EGL_NO_CONTEXT, context_attrib_list));
diff --git a/src/starboard/thread.h b/src/starboard/thread.h
index f1c73e5..b927984 100644
--- a/src/starboard/thread.h
+++ b/src/starboard/thread.h
@@ -29,14 +29,14 @@
 extern "C" {
 #endif
 
-#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION >= 12
 
 // An opaque handle to a thread type.
 typedef void* SbThread;
 
 #define kSbThreadInvalid (SbThread) NULL
 
-#endif  // SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+#endif  // SB_API_VERSION >= 12
 
 // A spectrum of thread priorities. Platforms map them appropriately to their
 // own priority system. Note that scheduling is platform-specific, and what
@@ -295,11 +295,11 @@
   // Pointer to the the current stack frame.
   kSbThreadContextFramePointer,
 
-#if SB_API_VERSION >= SB_THREAD_CONTEXT_LINK_REGISTER_VERSION
+#if SB_API_VERSION >= 12
   // Pointer to where to return to when the current function call completes, or
   // nullptr on platforms without a link register.
   kSbThreadContextLinkRegister,
-#endif  // SB_API_VERSION >= SB_THREAD_CONTEXT_LINK_REGISTER_VERSION
+#endif  // SB_API_VERSION >= 12
 } SbThreadContextProperty;
 
 // Gets the specified pointer-type |property| from the specified |context|.
diff --git a/src/starboard/thread_types.h b/src/starboard/thread_types.h
index 3c95a8e..5876085 100644
--- a/src/starboard/thread_types.h
+++ b/src/starboard/thread_types.h
@@ -31,7 +31,7 @@
 
 #include "starboard/configuration.h"
 
-#if SB_API_VERSION < SB_PORTABLE_THREAD_TYPES_VERSION
+#if SB_API_VERSION < 12
 
 // This platform-specific include file must define:
 //
@@ -62,5 +62,5 @@
 #error "SB_ONCE_INITIALIZER not defined by platform."
 #endif
 
-#endif  // SB_API_VERSION < SB_PORTABLE_THREAD_TYPES_VERSION
+#endif  // SB_API_VERSION < 12
 #endif  // STARBOARD_THREAD_TYPES_H_
diff --git a/src/starboard/time.h b/src/starboard/time.h
index 088f682..c71a700 100644
--- a/src/starboard/time.h
+++ b/src/starboard/time.h
@@ -91,10 +91,9 @@
 // Gets a monotonically increasing time representing right now.
 SB_EXPORT SbTimeMonotonic SbTimeGetMonotonicNow();
 
-#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION || \
-    SB_HAS(TIME_THREAD_NOW)
+#if SB_API_VERSION >= 12 || SB_HAS(TIME_THREAD_NOW)
 
-#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 // Returns whether the current platform supports time thread now
 SB_EXPORT bool SbTimeIsTimeThreadNowSupported();
 #endif
@@ -106,7 +105,7 @@
 // available then SbTimeGetMonotonicNow() should be used.
 SB_EXPORT SbTimeMonotonic SbTimeGetMonotonicThreadNow();
 
-#endif  // SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(TIME_THREAD_NOW)
 
 #ifdef __cplusplus
diff --git a/src/starboard/tools/abstract_launcher.py b/src/starboard/tools/abstract_launcher.py
index 0a86ec4..201e2f0 100644
--- a/src/starboard/tools/abstract_launcher.py
+++ b/src/starboard/tools/abstract_launcher.py
@@ -174,9 +174,40 @@
     Raises:
       RuntimeError: Suspend signal not supported on platform.
     """
-
     raise RuntimeError("Suspend not supported for this platform.")
 
+  def SendConceal(self):
+    """sends conceal signal to the launcher's executable.
+
+    Raises:
+      RuntimeError: Conceal signal not supported on platform.
+    """
+    raise RuntimeError("Conceal not supported for this platform.")
+
+  def SendFocus(self):
+    """sends focus signal to the launcher's executable.
+
+    Raises:
+      RuntimeError: focus signal not supported on platform.
+    """
+    raise RuntimeError("Focus not supported for this platform.")
+
+  def SendFreeze(self):
+    """sends freeze signal to the launcher's executable.
+
+    Raises:
+      RuntimeError: Freeze signal not supported on platform.
+    """
+    raise RuntimeError("Freeze not supported for this platform.")
+
+  def SendStop(self):
+    """sends stop signal to the launcher's executable.
+
+    Raises:
+      RuntimeError: Stop signal not supported on platform.
+    """
+    raise RuntimeError("Stop not supported for this platform.")
+
   def SupportsDeepLink(self):
     return False
 
@@ -186,17 +217,18 @@
     Args:
       link:  Link to send to the executable.
 
+    Returns:
+      True if the link was sent, False if it wasn't.
+
     Raises:
       RuntimeError: Deep link not supported on platform.
     """
-
     raise RuntimeError(
         "Deep link not supported for this platform (link {} sent).".format(
             link))
 
   def GetStartupTimeout(self):
     """Gets the number of seconds to wait before assuming a launcher timeout."""
-
     return self.startup_timeout_seconds
 
   def GetHostAndPortGivenPort(self, port):
diff --git a/src/starboard/tools/toolchain/abstract.py b/src/starboard/tools/toolchain/abstract.py
index 89f47d8..430b168 100644
--- a/src/starboard/tools/toolchain/abstract.py
+++ b/src/starboard/tools/toolchain/abstract.py
@@ -152,6 +152,17 @@
     """
     pass
 
+  def GetRestat(self):
+    """Returns a boolean controlling use of restat.
+
+    See 'restat' at https://ninja-build.org/manual.html#restat for
+    details.
+
+    Returns:
+      False if restat use is not specified.
+    """
+    return False
+
 
 class CCompiler(Tool):
   """Compiles C sources."""
@@ -294,6 +305,14 @@
     # Only applicable to C family compilers.
     return None
 
+  def GetFlags(self):
+    """Returns tool flags specific to a target.
+
+    Returns:
+      A list of flags.
+    """
+    return []
+
 
 class StaticThinLinker(Tool):
   """Creates thin archives using GNU ar."""
@@ -312,6 +331,13 @@
     # Only applicable to C family compilers.
     return None
 
+  def GetFlags(self):
+    """Returns tool flags specific to a target.
+
+    Returns:
+      A list of flags.
+    """
+    return []
 
 class ExecutableLinker(Tool):
   """Links executables."""
diff --git a/src/starboard/tools/toolchain/bash.py b/src/starboard/tools/toolchain/bash.py
index 1cd17c6..8d583c1 100644
--- a/src/starboard/tools/toolchain/bash.py
+++ b/src/starboard/tools/toolchain/bash.py
@@ -27,6 +27,10 @@
 class Shell(abstract.Shell):
   """Constructs command lines using Bash syntax."""
 
+  def __init__(self, quote=True):
+    # Toggle whether or not to quote command line arguments.
+    self.quote = quote
+
   def MaybeQuoteArgument(self, argument):
     # Rather than attempting to enumerate the bad shell characters, just
     # whitelist common OK ones and quote anything else.
@@ -38,7 +42,10 @@
 
   def Join(self, command):
     assert not isinstance(command, basestring)
-    return ' '.join(self.MaybeQuoteArgument(argument) for argument in command)
+    if self.quote:
+      return ' '.join(self.MaybeQuoteArgument(argument) for argument in command)
+    else:
+      return ' '.join(command)
 
   def And(self, *commands):
     return ' && '.join(_MaybeJoin(self, command) for command in commands)
diff --git a/src/starboard/tools/toolchain/evergreen_linker.py b/src/starboard/tools/toolchain/evergreen_linker.py
index 550adf4..aaef5b7 100644
--- a/src/starboard/tools/toolchain/evergreen_linker.py
+++ b/src/starboard/tools/toolchain/evergreen_linker.py
@@ -30,6 +30,7 @@
                      '-X '
                      '-v '
                      '--eh-frame-hdr '
+                     '--fini=__cxa_finalize '
                      '{2} '
                      '-shared '
                      '-o $out '
diff --git a/src/starboard/tools/toolchain/msvc.py b/src/starboard/tools/toolchain/msvc.py
new file mode 100644
index 0000000..a5be257
--- /dev/null
+++ b/src/starboard/tools/toolchain/msvc.py
@@ -0,0 +1,280 @@
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Allows use of MSVC build tools."""
+
+import sys
+
+from starboard.tools.toolchain import abstract
+from starboard.tools.toolchain import common
+
+
+def QuoteArguments(args):
+  return ['\"{0}\"'.format(arg.replace('"', '\\"')) for arg in args]
+
+
+class CompilerBase(object):
+  """A base class for MSVC-based compilers."""
+
+  def __init__(self, **kwargs):
+    self._path = common.GetPath('msvc', **kwargs)
+    self._gyp_defines = kwargs.get('gyp_defines', [])
+    self._gyp_include_dirs = kwargs.get('gyp_include_dirs', [])
+    self._gyp_cflags = kwargs.get('gyp_cflags', [])
+
+  def GetPath(self):
+    return self._path
+
+  def GetExtraFlags(self):
+    # Not used.
+    return []
+
+  def GetMaxConcurrentProcesses(self):
+    # Run as many concurrent processes as possible.
+    return None
+
+  def GetHeaderDependenciesFilePath(self):
+    pass
+
+  def GetHeaderDependenciesFormat(self):
+    return 'msvc'
+
+  def GetRspFilePath(self):
+    return '$out.rsp'
+
+  def GetRspFileContent(self):
+    return self._command_flags
+
+  def GetCommand(self, path, extra_flags, flags, shell):
+    del extra_flags  # Not used.
+    del shell  # Not used.
+    self._command_flags = flags
+    return ('{path} /nologo /showIncludes /FC @$out.rsp /c $in /Fo$out '
+            '/Fd$pdbname'.format(path=path))
+
+  def GetFlags(self, defines, include_dirs, cflags):
+    del cflags  # Not used.
+    defines = defines + self._gyp_defines
+    quoted_defines = QuoteArguments(defines)
+    define_flags = [
+        '/D{0}'.format(define) for define in quoted_defines
+    ]
+    include_dirs = include_dirs + self._gyp_include_dirs
+    quoted_include_dirs = QuoteArguments(include_dirs)
+    include_dir_flags = [
+        '/I{0}'.format(include_dir) for include_dir in quoted_include_dirs
+    ]
+    return define_flags + include_dir_flags + self._gyp_cflags
+
+
+class CCompiler(CompilerBase, abstract.CCompiler):
+  """Compiles C sources using MSVC."""
+
+  def GetDescription(self):
+    return 'CC $out'
+
+
+class CxxCompiler(CompilerBase, abstract.CxxCompiler):
+  """Compiles C++ sources using MSVC."""
+
+  def GetDescription(self):
+    return 'CXX $out'
+
+
+class AssemblerWithCPreprocessor(abstract.AssemblerWithCPreprocessor):
+  """Compiles assembler sources that contain C preprocessor directives."""
+
+  def __init__(self, **kwargs):
+    self._path = common.GetPath('masm', **kwargs)
+    self._arch = kwargs.get('arch', 'environment.x64')
+    self._gyp_defines = kwargs.get('gyp_defines', [])
+    self._gyp_include_dirs = kwargs.get('gyp_include_dirs', [])
+
+  def GetPath(self):
+    return self._path
+
+  def GetExtraFlags(self):
+    # Not used.
+    return []
+
+  def GetMaxConcurrentProcesses(self):
+    # Run as much concurrent processes as possible.
+    return None
+
+  def GetHeaderDependenciesFilePath(self):
+    pass
+
+  def GetHeaderDependenciesFormat(self):
+    pass
+
+  def GetRspFilePath(self):
+    pass
+
+  def GetRspFileContent(self):
+    pass
+
+  def GetCommand(self, path, extra_flags, flags, shell):
+    del extra_flags  # Not used.
+    del shell  # Not used.
+    return ('{python} gyp-win-tool asm-wrapper {arch} {path} {flags} /c /Fo '
+            '$out $in'.format(python=sys.executable, arch=self._arch,
+                              path=path, flags=flags))
+
+  def GetDescription(self):
+    return 'ASM $in'
+
+  def GetFlags(self, defines, include_dirs, cflags):
+    del cflags  # Not used.
+    defines = defines + self._gyp_defines
+    quoted_defines = QuoteArguments(defines)
+    define_flags = [
+        '/D{0}'.format(define) for define in quoted_defines
+    ]
+    include_dirs = include_dirs + self._gyp_include_dirs
+    quoted_include_dirs = QuoteArguments(include_dirs)
+    include_dir_flags = [
+        '/I{0}'.format(include_dir) for include_dir in quoted_include_dirs
+    ]
+    return define_flags + include_dir_flags
+
+
+class StaticLinkerBase(object):
+  """A base class for MSVC-based static linkers."""
+
+  def __init__(self, **kwargs):
+    self._path = common.GetPath('ar', **kwargs)
+    self._arch = kwargs.get('arch', 'environment.x64')
+    self._gyp_libflags = kwargs.get('gyp_libflags', [])
+
+  def GetPath(self):
+    return self._path
+
+  def GetExtraFlags(self):
+    # Not used.
+    return []
+
+  def GetMaxConcurrentProcesses(self):
+    # Run as much concurrent processes as possible.
+    return None
+
+  def GetDescription(self):
+    return 'LIB $out'
+
+  def GetRspFilePath(self):
+    return '$out.rsp'
+
+  def GetRspFileContent(self):
+    return '$in_newline ' + self._command_flags
+
+  def GetCommand(self, path, extra_flags, flags, shell):
+    del extra_flags  # Not used.
+    del shell  # Not used.
+    self._command_flags = flags
+    return ('{python} gyp-win-tool link-wrapper {arch} {path} /nologo '
+            '/ignore:4221 /OUT:$out @$out.rsp'.format(python=sys.executable,
+                                                      arch=self._arch,
+                                                      path=path))
+
+  def GetFlags(self):
+    return self._gyp_libflags
+
+
+class StaticLinker(StaticLinkerBase, abstract.StaticLinker):
+  """Creates self-contained archives using LIB.exe."""
+
+  def __init__(self, **kwargs):
+    super(StaticLinker, self).__init__(**kwargs)
+
+
+class StaticThinLinker(StaticLinkerBase, abstract.StaticThinLinker):
+  """Creates thin archives using LIB.exe."""
+
+  def __init__(self, **kwargs):
+    super(StaticThinLinker, self).__init__(**kwargs)
+
+
+class DynamicLinkerBase(object):
+  """A base class for MSVC-based executable and shared library linkers."""
+
+  def __init__(self, **kwargs):
+    self._path = common.GetPath('ld', **kwargs)
+    self._max_concurrent_processes = kwargs.get(
+        'max_concurrent_processes', common.EstimateMaxConcurrentLinkers())
+    self._arch = kwargs.get('arch', 'environment.x64')
+    self._gyp_ldflags = kwargs.get('gyp_ldflags', [])
+
+  def GetPath(self):
+    return self._path
+
+  def GetExtraFlags(self):
+    # Not used.
+    return []
+
+  def GetMaxConcurrentProcesses(self):
+    return self._max_concurrent_processes
+
+  def GetFlags(self, ldflags):
+    return ldflags + self._gyp_ldflags
+
+
+class ExecutableLinker(DynamicLinkerBase, abstract.ExecutableLinker):
+  """Links executables using LINK.exe."""
+
+  def __init__(self, **kwargs):
+    super(ExecutableLinker, self).__init__(**kwargs)
+
+  def GetDescription(self):
+    return 'LINK $out'
+
+  def GetRspFilePath(self):
+    return '$out.rsp'
+
+  def GetRspFileContent(self):
+    return '$in_newline ' + self._command_flags
+
+  def GetCommand(self, path, extra_flags, flags, shell):
+    del extra_flags  # Not used.
+    del shell  # Not used.
+    self._command_flags = flags
+    return ('{python} gyp-win-tool link-wrapper {arch} {path} /nologo '
+            '/OUT:$out /PDB:$out.pdb @$out.rsp'.format(python=sys.executable,
+                                                       arch=self._arch,
+                                                       path=path))
+
+
+class SharedLibraryLinker(DynamicLinkerBase, abstract.SharedLibraryLinker):
+  """Links shared libraries using LINK.exe."""
+
+  def __init__(self, **kwargs):
+    super(SharedLibraryLinker, self).__init__(**kwargs)
+
+  def GetDescription(self):
+    return 'LINK(DLL) $dll'
+
+  def GetRspFilePath(self):
+    return '$dll.rsp'
+
+  def GetRspFileContent(self):
+    return '$in_newline ' + self._command_flags
+
+  def GetCommand(self, path, extra_flags, flags, shell):
+    del extra_flags  # Not used.
+    del shell  # Not used.
+    self._command_flags = flags
+    return ('{python} gyp-win-tool link-wrapper {arch} {path} /nologo '
+            '$implibflag /DLL /OUT:$dll /PDB:$dll.pdb @$dll.rsp'.format(python=sys.executable,
+                                                      arch=self._arch,
+                                                      path=path))
+
+  def GetRestat(self):
+    return True
diff --git a/src/starboard/types.h b/src/starboard/types.h
index c3acfb7..2e7a448 100644
--- a/src/starboard/types.h
+++ b/src/starboard/types.h
@@ -25,68 +25,25 @@
 
 #include "starboard/configuration.h"
 
-#if SB_HAS(STDBOOL_H) && !defined(__cplusplus)
-#include <stdbool.h>
-#endif  // SB_HAS(STDBOOL_H) && !defined(__cplusplus)
-
-#if SB_HAS(STDINT_H)
-#include <stdint.h>
-#endif
-
-#if SB_HAS(INTTYPES_H)
+// The C library used must provide these headers to be standard conforming.
+#include <float.h>
 #include <inttypes.h>
-#endif  // SB_HAS(STDINT_H)
+#include <limits.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
 
 #if SB_HAS(SYS_TYPES_H)
 #include <sys/types.h>
 #endif  // SB_HAS(SYS_TYPES_H)
 
-#if SB_HAS(STDDEF_H)
-#include <stddef.h>
-#endif
-
-#if SB_HAS(LIMITS_H)
-#include <limits.h>
-#endif
-
-#if SB_HAS(STDARG_H)
-#include <stdarg.h>
-#endif
-
-#if SB_HAS(FLOAT_H)
-#include <float.h>
-#endif
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 // --- Standard Include Emulation ----------------------------------------------
 
-// Simulate stdint.h for platforms that don't provide it.
-#if !SB_HAS(STDINT_H) && !SB_HAS(INTTYPES_H)
-#if !defined(SB_INT8) || !defined(SB_UINT8) || !defined(SB_INT16) ||    \
-    !defined(SB_UINT16) || !defined(SB_INT32) || !defined(SB_UINT32) || \
-    !defined(SB_INT64) || !defined(SB_UINT64) || !defined(SB_INTPTR) || \
-    !defined(SB_UINTPTR)
-#error "No stdint.h or inttypes.h, so define SB_U?INT(8|16|32|64|PTR)."
-#endif  // !defined(SB_U?INT(8|16|32|64|PTR))
-typedef SB_INT8 int8_t;
-typedef SB_UINT8 uint8_t;
-
-typedef SB_INT16 int16_t;
-typedef SB_UINT16 uint16_t;
-
-typedef SB_INT32 int32_t;
-typedef SB_UINT32 uint32_t;
-
-typedef SB_INT64 int64_t;
-typedef SB_UINT64 uint64_t;
-
-typedef SB_INTPTR intptr_t;
-typedef SB_UINTPTR uintptr_t;
-#endif  // !SB_HAS(STDINT_H) && !SB_HAS(INTTYPES_H)
-
 #if !SB_HAS(SSIZE_T)
 #if SB_IS(32_BIT)
 typedef int32_t ssize_t;
@@ -95,73 +52,8 @@
 #endif
 #endif  // !SB_HAS(SSIZE_T)
 
-// Simulate stdbool.h for platforms that don't provide it.
-#if !SB_HAS(STDBOOL_H) && !defined(__cplusplus)
-#if __STDC_VERSION__ >= 199901L
-#define bool _Bool
-#else
-#define bool int
-#endif
-#define false 0
-#define true 1
-#endif  // !SB_HAS(STDBOOL_H) && !defined(__cplusplus)
-
-// Simulate stddef.h for platforms that don't provide it.
-#if !SB_HAS(STDDEF_H)
-#define NULL ((void*)0)
-#endif
-
 // Simulate needed portions of limits.h for platforms that don't provide it.
 
-// Assume int is 32-bits until we find a platform for which that fails.
-SB_COMPILE_ASSERT(sizeof(int) == sizeof(int32_t),  // NOLINT[runtime/int]
-                  starboard_int_is_32_bits);
-#if !defined(UINT_MAX)
-#define UINT_MAX 0xFFFFFFFFU
-#endif
-
-#if !defined(INT_MIN)
-#define INT_MIN 0x80000000
-#endif
-
-#if !defined(INT_MAX)
-#define INT_MAX 0x7FFFFFFF
-#endif
-
-#if SB_SIZE_OF(LONG) == 4
-
-SB_COMPILE_ASSERT(sizeof(long) == sizeof(int32_t),  // NOLINT[runtime/int]
-                  starboard_long_is_32_bits);
-#if !defined(LONG_MIN)
-#define LONG_MIN INT_MIN
-#endif
-
-#if !defined(LONG_MAX)
-#define LONG_MAX INT_MAX
-#endif
-
-#if !defined(ULONG_MAX)
-#define ULONG_MAX UINT_MAX
-#endif
-
-#else  // SB_SIZE_OF(LONG) == 8
-
-SB_COMPILE_ASSERT(sizeof(long) == sizeof(int64_t),  // NOLINT[runtime/int]
-                  starboard_long_is_64_bits);
-#if !defined(LONG_MIN)
-#define LONG_MIN SB_INT64_C(0x8000000000000000)
-#endif
-
-#if !defined(LONG_MAX)
-#define LONG_MAX SB_INT64_C(0x7FFFFFFFFFFFFFFF)
-#endif
-
-#if !defined(ULONG_MAX)
-#define ULONG_MAX SB_INT64_C(0xFFFFFFFFFFFFFFFF)
-#endif
-
-#endif  // SB_SIZE_OF(LONG) == 4
-
 #if defined(_MSC_VER)
 #pragma warning(push)
 #pragma warning(disable : 4310)  // Cast truncates constant value.
@@ -190,17 +82,8 @@
 // A value that represents an int that is probably invalid.
 #define kSbInvalidInt kSbInt32Min
 
-#if !SB_HAS(FLOAT_H)
-#define DBL_MANT_DIG 53
-#endif
-
 // --- Standard Include Emulation Audits ---------------------------------------
 
-#if !defined(UINT_MAX) || !defined(INT_MIN) || !defined(INT_MAX) || \
-    !defined(LONG_MIN) || !defined(LONG_MAX)
-#error "limits.h or emulation did not provide a needed limit macro."
-#endif
-
 #if (UINT_MIN + 1 == UINT_MAX - 1) || (INT_MIN + 1 == INT_MAX - 1) || \
     (LONG_MIN + 1 == LONG_MAX - 1)
 // This should always evaluate to false, but ensures that the limits macros can
diff --git a/src/starboard/ui_navigation.h b/src/starboard/ui_navigation.h
index 45543ba..adb1193 100644
--- a/src/starboard/ui_navigation.h
+++ b/src/starboard/ui_navigation.h
@@ -38,7 +38,7 @@
 #include "starboard/types.h"
 #include "starboard/window.h"
 
-#if SB_API_VERSION >= SB_UI_NAVIGATION_VERSION
+#if SB_API_VERSION >= 12
 
 #ifdef __cplusplus
 extern "C" {
@@ -268,6 +268,6 @@
 }  // extern "C"
 #endif
 
-#endif  // SB_API_VERSION >= SB_UI_NAVIGATION_VERSION
+#endif  // SB_API_VERSION >= 12
 
 #endif  // STARBOARD_UI_NAVIGATION_H_
diff --git a/src/starboard/window.h b/src/starboard/window.h
index df29899..b7e2771 100644
--- a/src/starboard/window.h
+++ b/src/starboard/window.h
@@ -139,8 +139,7 @@
 // |window|: The SbWindow to retrieve the platform handle for.
 SB_EXPORT void* SbWindowGetPlatformHandle(SbWindow window);
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
-    SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)
 
 // System-triggered OnScreenKeyboard events have ticket value
 // kSbEventOnScreenKeyboardInvalidTicket.
@@ -155,7 +154,7 @@
   float height;
 } SbWindowRect;
 
-#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+#if SB_API_VERSION >= 12
 // Return whether the current platform supports an on screen keyboard
 SB_EXPORT bool SbWindowOnScreenKeyboardIsSupported();
 #endif
@@ -230,7 +229,7 @@
 SB_EXPORT bool SbWindowOnScreenKeyboardSuggestionsSupported(SbWindow window);
 #endif  // SB_API_VERSION >= 11
 
-#endif  // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+#endif  // SB_API_VERSION >= 12 ||
         // SB_HAS(ON_SCREEN_KEYBOARD)
 
 #ifdef __cplusplus