Merge "Remove unused import" into main
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 8a0711c..e197b25 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -67,14 +67,14 @@
     {
       "name": "AvfRkpdAppGoogleIntegrationTests",
       "keywords": ["internal"]
+    },
+    {
+      "name": "TerminalAppTests"
     }
   ],
   "ferrochrome-postsubmit": [
     {
       "name": "ferrochrome-tests"
-    },
-    {
-      "name": "TerminalAppTests"
     }
   ],
   "postsubmit": [
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
index 7119225..a1509ad 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
@@ -19,6 +19,7 @@
 import android.app.Notification
 import android.app.NotificationManager
 import android.app.PendingIntent
+import android.content.Context
 import android.content.Intent
 import android.content.pm.PackageManager
 import android.graphics.drawable.Icon
@@ -34,14 +35,29 @@
         super.onCreate(savedInstanceState)
         setContentView(R.layout.settings_port_forwarding)
 
-        val settingsPortForwardingItems = arrayOf(
-            SettingsPortForwardingItem(8080, true),
-            SettingsPortForwardingItem(443, false),
-            SettingsPortForwardingItem(80, false)
+        val settingsPortForwardingItems = ArrayList<SettingsPortForwardingItem>()
+
+        val sharedPref = this.getSharedPreferences(
+            getString(R.string.preference_file_key), Context.MODE_PRIVATE
         )
 
+        val ports =
+            sharedPref.getStringSet(
+                getString(R.string.preference_forwarding_ports),
+                HashSet<String>()
+            )
+
+        for (port in ports!!) {
+            val enabled =
+                sharedPref.getBoolean(
+                    getString(R.string.preference_forwarding_port_is_enabled) + port,
+                    false
+                )
+            settingsPortForwardingItems.add(SettingsPortForwardingItem(port.toInt(), enabled));
+        }
+
         val settingsPortForwardingAdapter =
-            SettingsPortForwardingAdapter(settingsPortForwardingItems)
+            SettingsPortForwardingAdapter(settingsPortForwardingItems, this)
 
         val recyclerView: RecyclerView = findViewById(R.id.settings_port_forwarding_recycler_view)
         recyclerView.layoutManager = LinearLayoutManager(this)
@@ -59,7 +75,12 @@
                 .setChannelId(TAG)
                 .setSmallIcon(R.drawable.ic_launcher_foreground)
                 .setContentTitle(resources.getString(R.string.settings_port_forwarding_notification_title))
-                .setContentText(resources.getString(R.string.settings_port_forwarding_notification_content, settingsPortForwardingItems[0].port))
+                .setContentText(
+                    resources.getString(
+                        R.string.settings_port_forwarding_notification_content,
+                        8080
+                    )
+                )
                 .addAction(
                     Notification.Action.Builder(
                         Icon.createWithResource(resources, R.drawable.ic_launcher_foreground),
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingAdapter.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingAdapter.kt
index 1fa38e3..904f7f6 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingAdapter.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingAdapter.kt
@@ -15,6 +15,8 @@
  */
 package com.android.virtualization.terminal
 
+import android.content.Context
+import android.content.SharedPreferences
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
@@ -22,7 +24,10 @@
 import androidx.recyclerview.widget.RecyclerView
 import com.google.android.material.materialswitch.MaterialSwitch
 
-class SettingsPortForwardingAdapter(private val dataSet: Array<SettingsPortForwardingItem>) :
+class SettingsPortForwardingAdapter(
+    private val dataSet: ArrayList<SettingsPortForwardingItem>,
+    private val context: Context
+) :
     RecyclerView.Adapter<SettingsPortForwardingAdapter.ViewHolder>() {
 
     class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
@@ -40,6 +45,17 @@
     override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
         viewHolder.port.text = dataSet[position].port.toString()
         viewHolder.enabledSwitch.isChecked = dataSet[position].enabled
+        viewHolder.enabledSwitch.setOnCheckedChangeListener { _, isChecked ->
+            val sharedPref: SharedPreferences = context.getSharedPreferences(
+                context.getString(R.string.preference_file_key), Context.MODE_PRIVATE
+            )
+            val editor = sharedPref.edit()
+            editor.putBoolean(
+                context.getString(R.string.preference_forwarding_port_is_enabled) + viewHolder.port.text,
+                isChecked
+            )
+            editor.apply()
+        }
     }
 
     override fun getItemCount() = dataSet.size
diff --git a/android/TerminalApp/res/values/config.xml b/android/TerminalApp/res/values/config.xml
index 055abb7..9d2456c 100644
--- a/android/TerminalApp/res/values/config.xml
+++ b/android/TerminalApp/res/values/config.xml
@@ -18,4 +18,6 @@
     <string name="preference_file_key" translatable="false">com.android.virtualization.terminal.PREFERENCE_FILE_KEY</string>
     <string name="preference_disk_size_key" translatable="false">PREFERENCE_DISK_SIZE_KEY</string>
     <string name="preference_min_disk_size_key" translatable="false">PREFERENCE_MIN_DISK_SIZE_KEY</string>
+    <string name="preference_forwarding_ports" translatable="false">PREFERENCE_FORWARDING_PORTS</string>
+    <string name="preference_forwarding_port_is_enabled" translatable="false">PREFERENCE_FORWARDING_PORT_IS_ENABLED_</string>
 </resources>
\ No newline at end of file
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index d12f4bf..87d7a88 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -1154,6 +1154,13 @@
         }
     }
 
+    // Unfortunately specifying page_shift = 14 in bootconfig doesn't enable 16k pages emulation,
+    // so we need to provide it in the kernel cmdline.
+    // TODO(b/376901009): remove this after passing page_shift in bootconfig is supported.
+    if os_name.ends_with("_16k") && cfg!(target_arch = "x86_64") {
+        append_kernel_param("page_shift=14", &mut vm_config);
+    }
+
     if config.memoryMib > 0 {
         vm_config.memoryMib = config.memoryMib;
     }
@@ -2237,6 +2244,14 @@
     }
 
     #[test]
+    fn test_extract_os_name_from_microdroid_16k_config() -> Result<()> {
+        test_extract_os_name_from_config_path(
+            Path::new("/apex/com.android.virt/etc/microdroid_16k.json"),
+            Some("microdroid_16k"),
+        )
+    }
+
+    #[test]
     fn test_extract_os_name_from_microdroid_gki_config() -> Result<()> {
         test_extract_os_name_from_config_path(
             Path::new("/apex/com.android.virt/etc/microdroid_gki-android14-6.1.json"),
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index e940e71..4759c19 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -154,6 +154,14 @@
     }) + select(release_flag("RELEASE_AVF_ENABLE_NETWORK"), {
         true: ["com.android.virt.vmnic.rc"],
         default: [],
+    }) + select(soong_config_variable("ANDROID", "target_boots_16k"), {
+        true: [
+            "microdroid_16k_initrd_debuggable",
+            "microdroid_16k_initrd_normal",
+            "microdroid_kernel_16k",
+            "microdroid_16k.json",
+        ],
+        default: [],
     }),
     host_required: [
         "vm_shell",
diff --git a/build/apex/sign_virt_apex.py b/build/apex/sign_virt_apex.py
index 4a19c3d..e042f8d 100644
--- a/build/apex/sign_virt_apex.py
+++ b/build/apex/sign_virt_apex.py
@@ -523,6 +523,14 @@
             ret[f'gki-{ver}_initrd_normal.img']     = initrd_normal
             ret[f'gki-{ver}_initrd_debuggable.img'] = initrd_debug
 
+    kernel_16k = os.path.join(input_dir, 'etc/fs/microdroid_kernel_16k')
+    initrd_normal_16k = os.path.join(input_dir, 'etc/microdroid_16k_initrd_normal.img')
+    initrd_debug_16k = os.path.join(input_dir, 'etc/microdroid_16k_initrd_debuggable.img')
+    if os.path.isfile(kernel_16k):
+        ret['kernel_16k'] = kernel_16k
+        ret['16k_initrd_normal.img'] = initrd_normal_16k
+        ret['16k_initrd_debuggable.img'] = initrd_debug_16k
+
     return ret
 
 def IsInitrdImage(path):
diff --git a/build/debian/fai_config/files/etc/systemd/system/forwarder_guest_launcher.service/AVF b/build/debian/fai_config/files/etc/systemd/system/forwarder_guest_launcher.service/AVF
index 4c1b2f5..f4c2a24 100644
--- a/build/debian/fai_config/files/etc/systemd/system/forwarder_guest_launcher.service/AVF
+++ b/build/debian/fai_config/files/etc/systemd/system/forwarder_guest_launcher.service/AVF
@@ -4,7 +4,7 @@
 After=network.target
 After=virtiofs_internal.service
 [Service]
-ExecStart=/usr/local/bin/forwarder_guest_launcher --host 192.168.0.1 --grpc_port $(cat /mnt/internal/debian_service_port)
+ExecStart=/usr/bin/bash -c '/usr/local/bin/forwarder_guest_launcher --host 192.168.0.1 --grpc_port $(cat /mnt/internal/debian_service_port)'
 Type=simple
 Restart=on-failure
 RestartSec=1
diff --git a/build/debian/fai_config/files/etc/systemd/system/ip_addr_reporter.service/AVF b/build/debian/fai_config/files/etc/systemd/system/ip_addr_reporter.service/AVF
index 81347a7..b9f3193 100644
--- a/build/debian/fai_config/files/etc/systemd/system/ip_addr_reporter.service/AVF
+++ b/build/debian/fai_config/files/etc/systemd/system/ip_addr_reporter.service/AVF
@@ -5,7 +5,7 @@
 Requires=ttyd.service
 After=virtiofs_internal.service
 [Service]
-ExecStart=/usr/local/bin/ip_addr_reporter --grpc_port $(cat /mnt/internal/debian_service_port)
+ExecStart=/usr/bin/bash -c '/usr/local/bin/ip_addr_reporter --grpc_port $(cat /mnt/internal/debian_service_port)'
 Type=simple
 Restart=on-failure
 User=root
diff --git a/build/debian/vm_config.json.aarch64 b/build/debian/vm_config.json.aarch64
index 8e16093..2df0a05 100644
--- a/build/debian/vm_config.json.aarch64
+++ b/build/debian/vm_config.json.aarch64
@@ -12,7 +12,7 @@
             "sharedPath": "/storage/emulated"
         },
         {
-            "sharedPath": "/data/user/$USER_ID/$PACKAGE_NAME/files"
+            "sharedPath": "$APP_DATA_DIR/files"
         }
     ],
     "protected": false,
diff --git a/build/debian/vm_config.json.x86_64 b/build/debian/vm_config.json.x86_64
index 09e04b9..1719815 100644
--- a/build/debian/vm_config.json.x86_64
+++ b/build/debian/vm_config.json.x86_64
@@ -12,7 +12,7 @@
             "sharedPath": "/storage/emulated"
         },
         {
-            "sharedPath": "/data/user/$USER_ID/$PACKAGE_NAME/files"
+            "sharedPath": "$APP_DATA_DIR/files"
         }
     ],
     "kernel": "$PAYLOAD_DIR/vmlinuz",
diff --git a/build/microdroid/Android.bp b/build/microdroid/Android.bp
index abb97da..d5d8108 100644
--- a/build/microdroid/Android.bp
+++ b/build/microdroid/Android.bp
@@ -344,6 +344,11 @@
     cmd: "cat $(in) > $(out)",
 }
 
+filegroup {
+    name: "microdroid_16k_bootconfig_x86_64_gen",
+    srcs: ["bootconfig.x86_64_16k"],
+}
+
 prebuilt_etc {
     name: "microdroid_fstab",
     src: "fstab.microdroid",
@@ -377,6 +382,11 @@
 }
 
 prebuilt_etc {
+    name: "microdroid_16k.json",
+    src: "microdroid_16k.json",
+}
+
+prebuilt_etc {
     name: "microdroid_manifest",
     src: "microdroid_manifest.xml",
     filename: "manifest.xml",
@@ -431,6 +441,12 @@
     src: ":microdroid_initrd_normal",
 }
 
+avb_gen_vbmeta_image {
+    name: "microdroid_16k_initrd_normal_hashdesc",
+    defaults: ["microdroid_initrd_normal_defaults"],
+    src: ":microdroid_16k_initrd_normal",
+}
+
 // python -c "import hashlib; print(hashlib.sha256(b'initrd_debug').hexdigest())"
 initrd_debug_salt = "8ab9dc9cb7e6456700ff6ef18c6b4c3acc24c5fa5381b829563f8d7a415d869a"
 
@@ -447,6 +463,12 @@
     src: ":microdroid_initrd_debuggable",
 }
 
+avb_gen_vbmeta_image {
+    name: "microdroid_16k_initrd_debug_hashdesc",
+    defaults: ["microdroid_initrd_debug_defaults"],
+    src: ":microdroid_16k_initrd_debuggable",
+}
+
 soong_config_module_type {
     name: "flag_aware_avb_add_hash_footer_defaults",
     module_type: "avb_add_hash_footer_defaults",
@@ -521,6 +543,40 @@
     },
 }
 
+avb_add_hash_footer {
+    name: "microdroid_kernel_16k_signed",
+    defaults: ["microdroid_kernel_signed_defaults"],
+    filename: "microdroid_kernel_16k",
+    arch: {
+        arm64: {
+            src: ":microdroid_kernel_16k_prebuilt-arm64",
+        },
+        // There is no 16k x86_64 kernel. Instead the 16k emulation is triggered by adding
+        // `page_shift=14` to the kernel cmdline or bootconfig.
+        x86_64: {
+            src: ":microdroid_kernel_prebuilt-x86_64",
+        },
+    },
+    include_descriptors_from_images: [
+        ":microdroid_16k_initrd_normal_hashdesc",
+        ":microdroid_16k_initrd_debug_hashdesc",
+    ],
+}
+
+prebuilt_etc {
+    name: "microdroid_kernel_16k",
+    src: ":empty_file",
+    relative_install_path: "fs",
+    arch: {
+        arm64: {
+            src: ":microdroid_kernel_16k_signed",
+        },
+        x86_64: {
+            src: ":microdroid_kernel_16k_signed",
+        },
+    },
+}
+
 ///////////////////////////////////////
 // GKI-android15-6.6
 ///////////////////////////////////////
diff --git a/build/microdroid/bootconfig.x86_64_16k b/build/microdroid/bootconfig.x86_64_16k
new file mode 100644
index 0000000..ee01de5
--- /dev/null
+++ b/build/microdroid/bootconfig.x86_64_16k
@@ -0,0 +1 @@
+page_shift = 14
diff --git a/build/microdroid/initrd/Android.bp b/build/microdroid/initrd/Android.bp
index 6d45417..7331e0b 100644
--- a/build/microdroid/initrd/Android.bp
+++ b/build/microdroid/initrd/Android.bp
@@ -84,6 +84,10 @@
     ":microdroid_vbmeta_bootconfig_gen",
 ]
 
+bootconfigs_x86_64_16k = bootconfigs_x86_64 + [
+    ":microdroid_16k_bootconfig_x86_64_gen",
+]
+
 java_genrule {
     name: "microdroid_initrd_debuggable_arm64",
     tools: ["initrd_bootconfig"],
@@ -118,6 +122,17 @@
 }
 
 java_genrule {
+    name: "microdroid_16k_initrd_debuggable_x86_64",
+    tools: ["initrd_bootconfig"],
+    srcs: [
+        ":microdroid_initrd_gen",
+        ":microdroid_bootconfig_debuggable_src",
+    ] + bootconfigs_x86_64_16k,
+    out: ["microdroid_16k_initrd_debuggable_x86_64"],
+    cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
+}
+
+java_genrule {
     name: "microdroid_gki-android15-6.6_initrd_debuggable_x86_64",
     tools: ["initrd_bootconfig"],
     srcs: [
@@ -162,6 +177,17 @@
 }
 
 java_genrule {
+    name: "microdroid_16k_initrd_normal_x86_64",
+    tools: ["initrd_bootconfig"],
+    srcs: [
+        ":microdroid_initrd_gen",
+        ":microdroid_bootconfig_normal_src",
+    ] + bootconfigs_x86_64_16k,
+    out: ["microdroid_16k_initrd_normal_x86_64"],
+    cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
+}
+
+java_genrule {
     name: "microdroid_gki-android15-6.6_initrd_normal_x86_64",
     tools: ["initrd_bootconfig"],
     srcs: [
@@ -188,6 +214,24 @@
 }
 
 prebuilt_etc {
+    name: "microdroid_16k_initrd_debuggable",
+    // We don't have ramdisk for architectures other than x86_64 & arm64
+    src: ":empty_file",
+    arch: {
+        // For x86_64 we emulate 16k by adding `page_shift=14` to bootconfig, that's why we need
+        // separate initrd.
+        x86_64: {
+            src: ":microdroid_16k_initrd_debuggable_x86_64",
+        },
+        // For arm64, the initrd for 16k kernel is the same.
+        arm64: {
+            src: ":microdroid_initrd_debuggable_arm64",
+        },
+    },
+    filename: "microdroid_16k_initrd_debuggable.img",
+}
+
+prebuilt_etc {
     name: "microdroid_gki-android15-6.6_initrd_debuggable",
     // We don't have ramdisk for architectures other than x86_64 & arm64
     src: ":empty_file",
@@ -218,6 +262,24 @@
 }
 
 prebuilt_etc {
+    name: "microdroid_16k_initrd_normal",
+    // We don't have ramdisk for architectures other than x86_64 & arm64
+    src: ":empty_file",
+    arch: {
+        // For x86_64 we emulate 16k by adding `page_shift=14` to bootconfig, that's why we need
+        // separate initrd.
+        x86_64: {
+            src: ":microdroid_16k_initrd_normal_x86_64",
+        },
+        // For arm64, the initrd for 16k kernel is the same.
+        arm64: {
+            src: ":microdroid_initrd_normal_arm64",
+        },
+    },
+    filename: "microdroid_16k_initrd_normal.img",
+}
+
+prebuilt_etc {
     name: "microdroid_gki-android15-6.6_initrd_normal",
     // We don't have ramdisk for architectures other than x86_64 & arm64
     src: ":empty_file",
diff --git a/build/microdroid/microdroid_16k.json b/build/microdroid/microdroid_16k.json
new file mode 100644
index 0000000..ba6a949
--- /dev/null
+++ b/build/microdroid/microdroid_16k.json
@@ -0,0 +1,21 @@
+{
+  "kernel": "/apex/com.android.virt/etc/fs/microdroid_kernel_16k",
+  "disks": [
+    {
+      "partitions": [
+        {
+          "label": "vbmeta_a",
+          "path": "/apex/com.android.virt/etc/fs/microdroid_vbmeta.img"
+        },
+        {
+          "label": "super",
+          "path": "/apex/com.android.virt/etc/fs/microdroid_super.img"
+        }
+      ],
+      "writable": false
+    }
+  ],
+  "memory_mib": 256,
+  "console_input_device": "hvc0",
+  "platform_version": "~1.0"
+}
diff --git a/docs/service_vm.md b/docs/service_vm.md
index 735c14d..eedc6fd 100644
--- a/docs/service_vm.md
+++ b/docs/service_vm.md
@@ -16,9 +16,9 @@
 
 ## Architecture
 
-[Rialto](../rialto) is used as the bare-metal kernel for the Service VM. It
+[Rialto][rialto] is used as the bare-metal kernel for the Service VM. It
 shares some low-level setup, such as memory management and virtio device
-parsing, with pvmfw. The common setup code is grouped in [vmbase/](../libs/libvmbase).
+parsing, with pvmfw. The common setup code is grouped in [libvmbase/][libvmbase].
 
 ## Functionality
 
@@ -26,12 +26,21 @@
 and provide responses for each request. The requests and responses are
 serialized in CBOR format and transmitted over a virtio-vsock device.
 
--   [./comm](./comm) contains the definitions for the requests and responses.
--   [./requests](./requests) contains the library that processes the requests.
--   [./manager](./manager) manages the Service VM session, ensuring that only
-    one Service VM is active at any given time. The
-    [virtualizationservice](../android/virtualizationservice) process owns and manages
-    the Service VM instance.
+-   [libservice_vm_comm][libservice_vm_comm] contains the definitions for the
+    requests and responses.
+-   [libservice_vm_requests][libservice_vm_requests] contains the library that
+    processes the requests.
+-   [libservice_vm_manager][libservice_vm_manager] manages the Service VM
+    session, ensuring that only one Service VM is active at any given time. The
+    [virtualizationservice][virtualizationservice] process owns and manages the
+    Service VM instance.
+
+[rialto]: ../guest/rialto
+[libvmbase]: ../libs/libvmbase
+[libservice_vm_comm]: ../libs/libservice_vm_comm
+[libservice_vm_requests]: ../libs/libservice_vm_requests
+[libservice_vm_manager]: ../libs/libservice_vm_manager
+[virtualizationservice]: ../android/virtualizationservice
 
 ### RKP VM (Remote Key Provisioning Virtual Machine)
 
diff --git a/guest/kernel/Android.bp b/guest/kernel/Android.bp
index 8c6cccb..d3249f6 100644
--- a/guest/kernel/Android.bp
+++ b/guest/kernel/Android.bp
@@ -43,3 +43,12 @@
         default: [],
     }),
 }
+
+filegroup {
+    name: "microdroid_kernel_16k_prebuilt-arm64",
+    // Below are properties that are conditionally set depending on value of build flags.
+    srcs: select(release_flag("RELEASE_AVF_MICRODROID_KERNEL_VERSION"), {
+        "android15_66": ["android15-6.6/arm64/16k/kernel-6.6"],
+        default: [],
+    }),
+}
diff --git a/guest/pvmfw/src/bcc.rs b/guest/pvmfw/src/bcc.rs
index 7a13da7..5317ce9 100644
--- a/guest/pvmfw/src/bcc.rs
+++ b/guest/pvmfw/src/bcc.rs
@@ -109,10 +109,14 @@
             Value::Array(v) if v.len() >= 2 => v,
             _ => return Err(BccError::MalformedBcc("Invalid top level value")),
         };
-        // Decode all the entries to make sure they are well-formed.
-        let entries: Vec<_> = bcc.into_iter().skip(1).map(BccEntry::new).collect();
+        // Decode all the DICE payloads to make sure they are well-formed.
+        let payloads = bcc
+            .into_iter()
+            .skip(1)
+            .map(|v| BccEntry::new(v).payload())
+            .collect::<Result<Vec<_>>>()?;
 
-        let is_debug_mode = is_any_entry_debug_mode(entries.as_slice())?;
+        let is_debug_mode = is_any_payload_debug_mode(&payloads)?;
         Ok(Self { is_debug_mode })
     }
 
@@ -121,13 +125,13 @@
     }
 }
 
-fn is_any_entry_debug_mode(entries: &[BccEntry]) -> Result<bool> {
-    // Check if any entry in the chain is marked as Debug mode, which means the device is not
+fn is_any_payload_debug_mode(payloads: &[BccPayload]) -> Result<bool> {
+    // Check if any payload in the chain is marked as Debug mode, which means the device is not
     // secure. (Normal means it is a secure boot, for that stage at least; we ignore recovery
     // & not configured /invalid values, since it's not clear what they would mean in this
     // context.)
-    for entry in entries {
-        if entry.payload()?.is_debug_mode()? {
+    for payload in payloads {
+        if payload.is_debug_mode()? {
             return Ok(true);
         }
     }
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/InstallUtils.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/InstallUtils.java
index 0e46a63..f5cc912 100644
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/InstallUtils.java
+++ b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/InstallUtils.java
@@ -141,6 +141,12 @@
         rules.put("\\$PAYLOAD_DIR", new File(context.getFilesDir(), PAYLOAD_DIR).toString());
         rules.put("\\$USER_ID", String.valueOf(context.getUserId()));
         rules.put("\\$PACKAGE_NAME", context.getPackageName());
+        String appDataDir = context.getDataDir().toString();
+        // TODO: remove this hack
+        if (context.getUserId() == 0) {
+            appDataDir = "/data/data/" + context.getPackageName();
+        }
+        rules.put("\\$APP_DATA_DIR", appDataDir);
         return (s) -> {
             for (Map.Entry<String, String> rule : rules.entrySet()) {
                 s = s.replaceAll(rule.getKey(), rule.getValue());
diff --git a/tests/Terminal/Android.bp b/tests/Terminal/Android.bp
index 745a47c..cafbe93 100644
--- a/tests/Terminal/Android.bp
+++ b/tests/Terminal/Android.bp
@@ -15,8 +15,10 @@
         "androidx.test.core",
         "androidx.test.ext.junit",
         "junit",
+        "MicrodroidTestHelper",
     ],
     platform_apis: true,
-    test_suites: ["device-tests"],
+    test_suites: ["general-tests"],
     instrumentation_for: "VmTerminalApp",
+    data: ["TerminalAppTests-preparer.sh"],
 }
diff --git a/tests/Terminal/AndroidTest.xml b/tests/Terminal/AndroidTest.xml
index e9f549f..262421c 100644
--- a/tests/Terminal/AndroidTest.xml
+++ b/tests/Terminal/AndroidTest.xml
@@ -26,12 +26,8 @@
         <option name="force-root" value="true"/>
     </target_preparer>
 
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="throw-if-cmd-fail" value="true" />
-        <option name="run-command"
-            value="pm enable com.google.android.virtualization.terminal/com.android.virtualization.terminal.MainActivity" />
-        <option name="teardown-command"
-            value="pm disable com.google.android.virtualization.terminal/com.android.virtualization.terminal.MainActivity" />
+    <target_preparer class="com.android.tradefed.targetprep.RunHostScriptTargetPreparer">
+        <option name="script-file" value="TerminalAppTests-preparer.sh" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
diff --git a/tests/Terminal/TerminalAppTests-preparer.sh b/tests/Terminal/TerminalAppTests-preparer.sh
new file mode 100644
index 0000000..6022d7d
--- /dev/null
+++ b/tests/Terminal/TerminalAppTests-preparer.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Copyright 2024 Google Inc. 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.
+
+set -e
+
+serial=${ANDROID_SERIAL}
+user=$(adb -s ${serial} shell am get-current-user)
+
+# Enable the terminal app
+package_name=$(adb -s ${serial} shell pm list package virtualization.terminal | cut -d ':' -f 2)
+adb -s ${serial} shell pm enable --user ${user} ${package_name}
+
+# Identify file to download
+arch=$(adb -s ${serial} shell getprop ro.bionic.arch)
+if [ ${arch} == "arm64" ]; then
+  src=https://github.com/ikicha/debian_ci/releases/download/release_aarch64/images.tar.gz
+else
+  src=https://github.com/ikicha/debian_ci/releases/download/release_x86_64/images.tar.gz
+fi
+
+# Download
+downloaded=$(tempfile)
+wget ${src} -O ${downloaded}
+
+# Push the file to the device
+dst=/data/media/${user}/linux
+adb -s ${serial} shell mkdir -p ${dst}
+adb -s ${serial} push ${downloaded} ${dst}/images.tar.gz
diff --git a/tests/Terminal/src/com/android/virtualization/terminal/TerminalAppTest.java b/tests/Terminal/src/com/android/virtualization/terminal/TerminalAppTest.java
index 64ef79f..6400438 100644
--- a/tests/Terminal/src/com/android/virtualization/terminal/TerminalAppTest.java
+++ b/tests/Terminal/src/com/android/virtualization/terminal/TerminalAppTest.java
@@ -21,10 +21,12 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Bundle;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.microdroid.test.common.MetricsProcessor;
 import com.android.virtualization.vmlauncher.InstallUtils;
 
 import org.junit.After;
@@ -32,10 +34,15 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
 @RunWith(AndroidJUnit4.class)
 public class TerminalAppTest {
     private Instrumentation mInstr;
     private Context mTargetContext;
+    private final MetricsProcessor mMetricsProc = new MetricsProcessor("avf_perf/terminal/");
 
     @Before
     public void setup() {
@@ -65,9 +72,21 @@
         Intent intent = new Intent(mTargetContext, MainActivity.class);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
+        long start = System.currentTimeMillis();
         if (mInstr.startActivitySync(intent) instanceof MainActivity activity) {
             assertTrue("Failed to boot in 30s", activity.waitForBootCompleted(BOOT_TIMEOUT_MILLIS));
         }
+        long delay = System.currentTimeMillis() - start;
+
+        // TODO: measure multiple times?
+        List<Long> measurements = new ArrayList<>();
+        measurements.add(delay);
+        Map<String, Double> stats = mMetricsProc.computeStats(measurements, "boot", "ms");
+        Bundle bundle = new Bundle();
+        for (Map.Entry<String, Double> entry : stats.entrySet()) {
+            bundle.putDouble(entry.getKey(), entry.getValue());
+        }
+        mInstr.sendStatus(0, bundle);
     }
 
     @After
diff --git a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
index e81f6d7..6a3bc1b 100644
--- a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
+++ b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
@@ -70,6 +70,9 @@
     /** Returns flags for the given mountPoint. */
     int getMountFlags(String mountPoint);
 
+    /** Returns page size of the VM. */
+    int getPageSize();
+
     /** Requests the VM to asynchronously call appCallback.setVmCallback() */
     void requestCallback(IAppCallback appCallback);
 
diff --git a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
index ceebb52..e2ee381 100644
--- a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
+++ b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
@@ -594,7 +594,7 @@
         @Override
         public void onPayloadReady(VirtualMachine vm, IBenchmarkService service)
                 throws RemoteException {
-            int vmPid = ProcessUtil.getCrosvmPid(Os.getpid(), mShellExecutor);
+            int vmPid = ProcessUtil.getCrosvmPid(Os.getpid(), "test_vm_mem_usage", mShellExecutor);
 
             mMemTotal = service.getMemInfoEntry("MemTotal");
             mMemFree = service.getMemInfoEntry("MemFree");
@@ -668,7 +668,8 @@
         @SuppressWarnings("ReturnValueIgnored")
         public void onPayloadReady(VirtualMachine vm, IBenchmarkService service)
                 throws RemoteException {
-            int vmPid = ProcessUtil.getCrosvmPid(Os.getpid(), mShellExecutor);
+            int vmPid =
+                    ProcessUtil.getCrosvmPid(Os.getpid(), "test_vm_mem_reclaim", mShellExecutor);
 
             // Allocate 256MB of anonymous memory. This will fill all guest
             // memory and cause swapping to start.
diff --git a/tests/helper/src/java/com/android/microdroid/test/common/ProcessUtil.java b/tests/helper/src/java/com/android/microdroid/test/common/ProcessUtil.java
index c4aba81..c544b77 100644
--- a/tests/helper/src/java/com/android/microdroid/test/common/ProcessUtil.java
+++ b/tests/helper/src/java/com/android/microdroid/test/common/ProcessUtil.java
@@ -127,9 +127,10 @@
         return getSingleChildProcess(parentPid, VIRTMGR_BIN, shellExecutor);
     }
 
-    public static int getCrosvmPid(int parentPid, Function<String, String> shellExecutor) {
+    public static int getCrosvmPid(
+            int parentPid, String testName, Function<String, String> shellExecutor) {
         int virtmgrPid = getVirtmgrPid(parentPid, shellExecutor);
-        return getSingleChildProcess(virtmgrPid, CROSVM_BIN, shellExecutor);
+        return getSingleChildProcess(virtmgrPid, "crosvm_" + testName, shellExecutor);
     }
 
     // To ensures that only one object is created at a time.
diff --git a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
index 72e5c75..2986bdc 100644
--- a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
+++ b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
@@ -72,7 +72,11 @@
     protected static final String KERNEL_VERSION = SystemProperties.get("ro.kernel.version");
     protected static final Set<String> SUPPORTED_OSES =
             Collections.unmodifiableSet(
-                    new HashSet<>(Arrays.asList("microdroid", "microdroid_gki-android15-6.6")));
+                    new HashSet<>(
+                            Arrays.asList(
+                                    "microdroid",
+                                    "microdroid_16k",
+                                    "microdroid_gki-android15-6.6")));
 
     public static boolean isCuttlefish() {
         return getDeviceProperties().isCuttlefish();
@@ -205,6 +209,10 @@
             assume().withMessage("Testing protected VMs on GSI isn't supported. b/272443823")
                     .that(isGsi())
                     .isFalse();
+            // TODO(b/376870129): remove this
+            assume().withMessage("pVMs with 16k kernel are not supported yet :(")
+                    .that(mOs)
+                    .doesNotContain("_16k");
         } else {
             assume().withMessage("Skip where VMs aren't supported")
                     .that(capabilities & VirtualMachineManager.CAPABILITY_NON_PROTECTED_VM)
@@ -579,6 +587,7 @@
         public int mMountFlags;
         public String mConsoleInput;
         public byte[] mInstanceSecret;
+        public int mPageSize;
 
         public void assertNoException() {
             if (mException != null) {
diff --git a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
index 811d8db..ad37dda 100644
--- a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
+++ b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
@@ -73,6 +73,7 @@
     protected static final Map<String, String> SUPPORTED_OSES =
             Map.ofEntries(
                     Map.entry("microdroid", "microdroid"),
+                    Map.entry("microdroid_16k", "microdroid_16k"),
                     Map.entry("android15_66", "microdroid_gki-android15-6.6"));
 
     /* Keep this sync with AssignableDevice.aidl */
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 20f71e5..adab521 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -415,7 +415,7 @@
     @VsrTest(requirements = {"VSR-7.1-001.008"})
     public void UpgradedPackageIsAcceptedWithSecretkeeper() throws Exception {
         // Preconditions
-        assumeVmTypeSupported(true); // Non-protected VMs may not support upgrades
+        assumeVmTypeSupported("microdroid", true); // Non-protected VMs may not support upgrades
         ensureUpdatableVmSupported();
         getDevice().uninstallPackage(PACKAGE_NAME);
         getDevice().installPackage(findTestFile(APK_NAME), /* reinstall= */ true);
@@ -433,7 +433,7 @@
     @VsrTest(requirements = {"VSR-7.1-001.008"})
     public void DowngradedPackageIsRejectedProtectedVm() throws Exception {
         // Preconditions: Rollback protection is provided only for protected VM.
-        assumeVmTypeSupported(true);
+        assumeVmTypeSupported("microdroid", true);
 
         // Install the upgraded version (v6)
         getDevice().uninstallPackage(PACKAGE_NAME);
@@ -483,7 +483,7 @@
     public void protectedVmRunsPvmfw(String os) throws Exception {
         // Arrange
         assumeKernelSupported(os);
-        assumeVmTypeSupported(true);
+        assumeVmTypeSupported(os, true);
         final String configPath = "assets/vm_config_apex.json";
 
         // Act
@@ -516,7 +516,7 @@
     public void protectedVmWithImageSignedWithDifferentKeyFailsToVerifyPayload(String os)
             throws Exception {
         assumeKernelSupported(os);
-        assumeVmTypeSupported(true);
+        assumeVmTypeSupported(os, true);
         File key = findTestFile("test.com.android.virt.pem");
 
         // Act
@@ -664,7 +664,7 @@
             throws Exception {
         // Preconditions
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
         // TODO(b/291867858): tombstones are failing in HWASAN enabled Microdroid.
         assumeFalse("tombstones are failing in HWASAN enabled Microdroid.", isHwasan());
         assertThat(
@@ -685,7 +685,7 @@
             boolean protectedVm, String os) throws Exception {
         // Preconditions
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
         // TODO(b/291867858): tombstones are failing in HWASAN enabled Microdroid.
         assumeFalse("tombstones are failing in HWASAN enabled Microdroid.", isHwasan());
         assertThat(
@@ -707,7 +707,7 @@
             throws Exception {
         // Preconditions
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
         assumeFalse("Cuttlefish is not supported", isCuttlefish());
         assumeFalse("Skipping test because ramdump is disabled on user build", isUserBuild());
 
@@ -784,7 +784,7 @@
         // TODO(b/291867858): tombstones are failing in HWASAN enabled Microdroid.
         assumeFalse("tombstones are failing in HWASAN enabled Microdroid.", isHwasan());
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
 
         // Act
         assertThat(isTombstoneGeneratedWithCrashPayload(protectedVm, os, /* debuggable= */ true))
@@ -800,7 +800,7 @@
         // TODO(b/291867858): tombstones are failing in HWASAN enabled Microdroid.
         assumeFalse("tombstones are failing in HWASAN enabled Microdroid.", isHwasan());
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
 
         // Act
         assertThat(isTombstoneGeneratedWithCrashPayload(protectedVm, os, /* debuggable= */ false))
@@ -822,7 +822,7 @@
         // TODO(b/291867858): tombstones are failing in HWASAN enabled Microdroid.
         assumeFalse("tombstones are failing in HWASAN enabled Microdroid.", isHwasan());
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
 
         // Act
         assertThat(isTombstoneGeneratedWithCrashConfig(protectedVm, os, /* debuggable= */ true))
@@ -837,7 +837,7 @@
         // TODO(b/291867858): tombstones are failing in HWASAN enabled Microdroid.
         assumeFalse("tombstones are failing in HWASAN enabled Microdroid.", isHwasan());
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
         assertThat(isTombstoneGeneratedWithCrashConfig(protectedVm, os, /* debuggable= */ false))
                 .isFalse();
     }
@@ -847,7 +847,7 @@
     @TestCaseName("{method}_protectedVm_{0}_os_{1}")
     public void testTelemetryPushedAtoms(boolean protectedVm, String os) throws Exception {
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
         // Reset statsd config and report before the test
         ConfigUtils.removeConfig(getDevice());
         ReportUtils.clearReports(getDevice());
@@ -1011,7 +1011,7 @@
     public void testMicrodroidBoots(boolean protectedVm, String os) throws Exception {
         // Preconditions
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
 
         final String configPath = "assets/vm_config.json"; // path inside the APK
         testMicrodroidBootsWithBuilder(
@@ -1049,7 +1049,7 @@
     void checkMicrodroidRamUsage(boolean protectedVm, String os) throws Exception {
         // Preconditions
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
 
         final String configPath = "assets/vm_config.json";
         mMicrodroidDevice =
@@ -1245,7 +1245,7 @@
     public void testDeviceAssignment(boolean protectedVm, String os) throws Exception {
         // Preconditions
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
         assumeVfioPlatformSupported();
 
         List<AssignableDevice> devices = getAssignableDevices();
@@ -1309,7 +1309,7 @@
     public void testHugePages(boolean protectedVm, String os) throws Exception {
         // Preconditions
         assumeKernelSupported(os);
-        assumeVmTypeSupported(protectedVm);
+        assumeVmTypeSupported(os, protectedVm);
 
         ITestDevice device = getDevice();
         boolean disableRoot = !device.isAdbRoot();
@@ -1382,7 +1382,7 @@
         final String configPath = "assets/vm_config.json";
         // Preconditions
         assumeKernelSupported(os);
-        assumeVmTypeSupported(true);
+        assumeVmTypeSupported(os, true);
         int mem_size = 256;
         assertTrue("Memory size too small", mem_size >= minMemorySize());
 
@@ -1551,7 +1551,11 @@
                 getSupportedOSList().contains(os));
     }
 
-    private void assumeVmTypeSupported(boolean protectedVm) throws Exception {
+    private void assumeVmTypeSupported(String os, boolean protectedVm) throws Exception {
+        // TODO(b/376870129): remove this check
+        if (protectedVm) {
+            assumeFalse("pVMs with 16k kernel are not supported yet :(", os.endsWith("_16k"));
+        }
         assumeTrue(
                 "Microdroid is not supported for specific VM protection type",
                 getAndroidDevice().supportsMicrodroid(protectedVm));
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index 53fc819..917a027 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -2511,6 +2511,30 @@
         assertThat(testResults.mMountFlags & expectedFlags).isEqualTo(expectedFlags);
     }
 
+    @Test
+    public void pageSize() throws Exception {
+        assumeSupportedDevice();
+
+        VirtualMachineConfig config =
+                newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                        .setDebugLevel(DEBUG_LEVEL_FULL)
+                        .build();
+
+        VirtualMachine vm = forceCreateNewVirtualMachine("test_page_size", config);
+
+        TestResults testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mPageSize = ts.getPageSize();
+                        });
+
+        assertThat(testResults.mException).isNull();
+        int expectedPageSize = mOs.endsWith("_16k") ? 16384 : 4096;
+        assertThat(testResults.mPageSize).isEqualTo(expectedPageSize);
+    }
+
     private static class VmShareServiceConnection implements ServiceConnection {
 
         private final CountDownLatch mLatch = new CountDownLatch(1);
diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp
index 1a75102..632f648 100644
--- a/tests/testapk/src/native/testbinary.cpp
+++ b/tests/testapk/src/native/testbinary.cpp
@@ -34,6 +34,7 @@
 #include <vm_main.h>
 #include <vm_payload_restricted.h>
 
+#include <cstdint>
 #include <string>
 #include <thread>
 
@@ -311,6 +312,11 @@
             return ScopedAStatus::ok();
         }
 
+        ScopedAStatus getPageSize(int32_t* out) override {
+            *out = getpagesize();
+            return ScopedAStatus::ok();
+        }
+
         ScopedAStatus requestCallback(const std::shared_ptr<IAppCallback>& appCallback) {
             auto vmCallback = ndk::SharedRefBase::make<VmCallbackImpl>(appCallback);
             std::thread callback_thread{[=] { appCallback->setVmCallback(vmCallback); }};
diff --git a/tests/testapk/src/native/testbinary.rs b/tests/testapk/src/native/testbinary.rs
index 85b411e..e479342 100644
--- a/tests/testapk/src/native/testbinary.rs
+++ b/tests/testapk/src/native/testbinary.rs
@@ -123,6 +123,9 @@
     fn getMountFlags(&self, _: &str) -> BinderResult<i32> {
         unimplemented()
     }
+    fn getPageSize(&self) -> BinderResult<i32> {
+        unimplemented()
+    }
     fn requestCallback(&self, _: &Strong<dyn IAppCallback + 'static>) -> BinderResult<()> {
         unimplemented()
     }
diff --git a/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java b/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
index 9f606e5..13b0c51 100644
--- a/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
+++ b/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
@@ -258,6 +258,11 @@
         }
 
         @Override
+        public int getPageSize() throws RemoteException {
+            throw new UnsupportedOperationException("Not supported");
+        }
+
+        @Override
         public void requestCallback(IAppCallback appCallback) {
             throw new UnsupportedOperationException("Not supported");
         }