How to Create a Custom ROM for Android Made Easy

Android61 Views

How to Create a Custom ROM for Android sets the stage for this enthralling narrative, offering readers a glimpse into a story that is rich in detail and brimming with originality from the outset. Custom ROMs provide an exciting opportunity for Android enthusiasts to enhance their devices beyond the limitations of stock firmware. This guide will delve into the history, significance, and practical steps involved in creating your own custom ROM, empowering you to tailor your Android experience to your liking.

Table of Contents

Introduction to Custom ROMs

Custom ROMs are modified versions of the Android operating system, designed to offer users an alternative to the stock ROMs that come pre-installed on their devices. These custom builds provide unique features, user interface tweaks, and performance enhancements that may not be available in the standard version. As a result, users often choose custom ROMs to improve their device’s functionality, extend its lifespan, or enjoy a more personalized experience.The history of Android ROM development dates back to the early days of the platform when enthusiasts began modifying the Android OS to unlock additional features and customize their devices.

Over time, communities like XDA Developers emerged, fostering a culture of collaboration and innovation among developers and users. This evolution has led to the creation of a vast array of custom ROMs, each catering to different preferences and device capabilities. Today, popular custom ROMs like LineageOS, Paranoid Android, and Pixel Experience are widely recognized for their contributions to the Android ecosystem.Custom ROMs hold significant importance within the Android community.

They empower users to take control of their devices, bypassing the limitations imposed by manufacturers and carriers. This not only promotes a diverse range of user experiences but also encourages developers to innovate continuously. Moreover, custom ROMs often receive regular updates and security patches, contributing to a safer and more stable Android environment. The thriving custom ROM scene is a testament to Android’s open-source nature, allowing users to tailor their devices to meet their individual needs and preferences.

Advantages of Custom ROMs over Stock ROMs

The benefits of using custom ROMs can significantly enhance the user experience. Here are some key advantages that custom ROMs offer over stock ROMs:

  • Customization: Custom ROMs provide extensive customization options, allowing users to modify themes, icons, and layouts to suit their preferences.
  • Performance Improvements: Many custom ROMs are optimized for better performance, resulting in smoother operation and less lag.
  • Regular Updates: Custom ROMs often receive frequent updates and security patches, ensuring that users have the latest features and security enhancements.
  • Bloatware Removal: Users can enjoy a cleaner experience by eliminating pre-installed apps that come with stock ROMs, which are often unnecessary.
  • Access to Latest Features: Custom ROMs may provide access to features not yet available in the stock version, such as the latest Android version or experimental functionalities.

“Custom ROMs not only enhance usability but also extend the device’s life beyond the manufacturer’s support period.”

Prerequisites for Creating a Custom ROM

Creating a custom ROM for Android devices requires a solid foundation of tools, software, and hardware. It’s not just about having a desire to tinker with your device; it’s essential to ensure you have the right resources to develop an effective and stable ROM. This section will Artikel the crucial prerequisites needed to kickstart your custom ROM development journey.

Necessary Tools and Software for ROM Development

When diving into custom ROM development, having the right tools and software is paramount. These resources enable you to build, modify, and test your ROMs efficiently. Below is a list of essential tools to consider:

  • Android SDK: This software development kit contains essential tools for Android development, including adb (Android Debug Bridge) and fastboot, which are critical for managing Android devices.
  • Build Environment: Setting up a Linux environment (Ubuntu is highly recommended) is crucial, as most Android builds are performed in this ecosystem. You’ll need tools like Git and various compilers and libraries.
  • Custom Recovery: A custom recovery like TWRP (Team Win Recovery Project) is necessary for flashing your ROM onto your device and for taking backups.
  • Source Code: Accessing the Android Open Source Project (AOSP) or specific device trees from manufacturers is essential for building your ROM from the ground up.
  • Text Editor/IDE: Choosing a capable text editor (like Visual Studio Code or Sublime Text) or an IDE (like Android Studio) will aid in writing and editing code efficiently.

Hardware Requirements for Building a Custom ROM

Building a custom ROM is not just a software endeavor; it also has specific hardware requirements to ensure smooth operation. Adequate hardware can significantly enhance the development experience and efficiency. Consider the following:

  • PC Specifications: A computer with at least 8 GB of RAM is recommended, although 16 GB will provide a smoother experience. A multi-core processor will help in faster compilation times.
  • Storage Space: Depending on the size of the ROM and additional files, having at least 100 GB of free disk space is advisable, allowing for smooth storage of source files and compiled ROMs.
  • Device for Testing: It is crucial to have a test device that is compatible with your ROM. This device should ideally have an unlocked bootloader to facilitate the flashing process.

Importance of Having an Unlocked Bootloader

An unlocked bootloader is a critical requirement for creating and installing custom ROMs. This feature allows you to modify the system partition of your device, making it possible to flash a custom ROM. Here’s why it’s important:

An unlocked bootloader is essential for flashing custom ROMs, as it grants access to the device’s internal storage and system files, allowing modifications that are not possible with a locked bootloader.

Having an unlocked bootloader not only simplifies the ROM installation process but also enables the use of custom recoveries and rooting methods. However, it is vital to note that unlocking the bootloader may void your warranty and potentially expose your device to security vulnerabilities.

Setting Up the Development Environment

Creating a custom ROM for Android requires a robust development environment. This is crucial for compiling the source code and testing your ROM effectively. In this section, we will Artikel the essential steps for installing Android Studio, setting up the Android SDK, and configuring your build environment.

Installing Android Studio

Android Studio is the official integrated development environment (IDE) for Android development. To get started, follow these steps for installation:

1. Visit the [Android Studio download page](https

//developer.android.com/studio) and download the installer for your operating system.

2. Run the installer

Windows

Double-click the downloaded `.exe` file and follow the setup wizard.

macOS

Open the `.dmg` file, drag and drop Android Studio to your Applications folder.

Linux

Extract the downloaded `.zip` file and run the `studio.sh` script in the `bin` directory.Launch Android Studio once the installation is complete. The setup wizard guides you through the process, prompting you to install the necessary SDK components.

Setting Up the Android SDK and Dependencies

The Android SDK is essential for developing Android applications and is included with Android Studio. However, ensuring all dependencies are correctly installed is vital for a smooth development experience. Here’s how to set it up:

  • Launch Android Studio and navigate to `File` > `Settings` (or `Android Studio` > `Preferences` on macOS).
  • Select the `Appearance & Behavior` tab and then `System Settings` > `Android SDK`.
  • Under the SDK Platforms tab, check the box for the latest version of Android (e.g., Android 13) and click `Apply`.
  • Switch to the SDK Tools tab and ensure the following components are installed

Android SDK Build-Tools

Android SDK Platform-Tools

Android Emulator

Intel x86 Emulator Accelerator (HAXM Installer) for better emulation performance.

Important Note: Make sure to keep the SDK updated regularly for optimal functionality and compatibility.

Configuring a Build Environment on Your Computer

Setting up a proper build environment involves configuring your computer to handle the compilation process. This includes installing necessary tools and setting environment variables.

1. Install Java Development Kit (JDK)

Download and install the latest JDK from the [Oracle website](https

//www.oracle.com/java/technologies/javase-downloads.html). Set the `JAVA_HOME` environment variable to the JDK installation path.

2. Install Git for Version Control

Download Git from the [official site](https

//git-scm.com/downloads) and install it.

Set up your Git configuration by running

`git config –global user.name “Your Name”`

`git config –global user.email “youremail@example.com”`

3. Set Up Environment Variables

Add the paths to the Android SDK and JDK in your system’s environment variables

For Windows, navigate to `Control Panel` > `System and Security` > `System` > `Advanced system settings` > `Environment Variables`.

For macOS and Linux, add the following lines to your `.bashrc` or `.zshrc`

“`bash export ANDROID_HOME=~/Android/Sdk export PATH=$PATH:$ANDROID_HOME/tools export PATH=$PATH:$ANDROID_HOME/platform-tools export JAVA_HOME=/path/to/your/jdk “`

4. Verify Your Setup

Open a terminal and run the command

“`bash adb version “`

This should display the installed version of the Android Debug Bridge (ADB), confirming your environment is set up correctly.

“It’s essential to have all components up-to-date to avoid potential issues during ROM development.”

With these steps completed, your development environment will be ready for creating custom ROMs, allowing for an efficient workflow as you embark on your Android customization journey.

Downloading the Android Source Code: How To Create A Custom ROM For Android

Accessing the Android Open Source Project (AOSP) is a fundamental step in creating a custom ROM for Android. AOSP provides the source code needed to build Android from the ground up, allowing developers to customize and enhance the operating system according to their needs. This section will guide you through the process of downloading the correct version of the source code and understanding its structure for effective modifications.

Accessing the Android Open Source Project (AOSP)

The first step is to navigate to the official Android Open Source Project website. AOSP is hosted on various platforms, with the primary repository located on Google’s source management site. To access AOSP:

1. Visit the Android source site at Downloading the Correct Version of the Source Code

Downloading the appropriate version of the Android source code is crucial, especially since multiple versions are available for different devices and builds. It’s essential to choose a version that is compatible with the device you are targeting for your custom ROM.To download the source code:Set up the repo tool by following the instructions on the AOSP website. This tool helps manage multiple Git repositories.

2. Open a terminal and create a directory for your workspace using the command

“`bash mkdir ~/aosp cd ~/aosp “`Initialize the repo. Depending on the version you want to download, the command may look like this for Android 12: “`bash repo init -u https://android.googlesource.com/platform/manifest -b android-12.0.0_r1 “`

4. Sync the repo to download the source code

“`bash repo sync “`

This process may take some time depending on your internet connection and the size of the source code.

Understanding the Structure of the Source Code

Understanding the structure of the Android source code is vital for effective customization. The code is organized into various directories, each serving a specific purpose.Key directories include:

  • frameworks: Contains the core framework code and libraries essential for Android applications.
  • system: Includes lower-level system components, such as the Android Runtime (ART).
  • packages: Contains applications and system services that are part of the Android operating system.
  • hardware: Defines the HAL (Hardware Abstraction Layer) which allows the Android system to communicate with hardware components.

Understanding this structure helps developers navigate through the codebase efficiently, making it easier to implement changes or optimizations.

Knowledge of the source code structure is key to navigating and modifying AOSP effectively.

Customizing the ROM

Customizing an Android ROM is an essential part of making it unique and tailored to specific user preferences. It allows developers to modify the user experience, make system applications more functional, and introduce fresh features that enhance usability. This section Artikels key methods for effectively customizing an Android ROM.

Modifying System Applications and Frameworks

Changing system applications and frameworks involves delving into the core functionalities of Android. This customization enables enhanced performance and personalized user experiences. To modify these components, developers should consider the following methods:

Decompiling APKs

Use tools such as APKTool to decompile system applications, which allows you to modify resources and code. Changes can include altering app layouts, icons, and functionalities.

Editing Framework Files

Access and modify framework files located in the `/framework` directory. This can include changing system libraries and services to enhance the overall performance and responsiveness of the ROM.

Recompiling and Signing

After making changes, recompile the APKs and sign them with a debug or release key. This step is crucial, as unsigned APKs will not install on the system.

“Modifying system applications can significantly enhance the performance and usability of your custom ROM.”

Implementing Custom Themes and UI Changes

Custom themes and UI changes can dramatically alter the appearance of the ROM, making it visually appealing and more aligned with user preferences. Here are several techniques to implement these customizations:

Substratum Theme Engine

By integrating Substratum, users can apply system-wide themes without altering the core files. This tool allows for granular control over various UI elements.

Creating a Custom Bootanimation

Replace the stock boot animation with a personalized one. This involves creating a ZIP file with your animations and placing it in the `/system/media` directory.

Reskinning the User Interface

Modify the styles.xml and colors.xml files within the framework-res.apk to change colors, button styles, and other UI elements. This can help in creating a cohesive visual style across all aspects of the ROM.

“Custom themes not only enhance aesthetics but can also improve system navigation and user engagement.”

Adding New Features and Functionalities

Introducing new features is what makes a custom ROM stand out from stock versions. Developers can enhance functionality by incorporating the following techniques:

Integrating Custom Features

Add unique functionalities such as advanced multitasking, enhanced privacy controls, or custom gesture support. Utilize frameworks like Xposed to implement these without extensive modifications to the system.

Developing Proprietary Apps

Create and bundle proprietary applications that provide added functionalities, like better battery management or enhanced security features. This increases the value of the custom ROM for end-users.

Using Configuration Files

Many features can be toggled through configuration files located in `/system/build.prop`. Adjustments can optimize network performance, battery life, and system responsiveness.

“Adding unique features not only improves usability but also differentiates your ROM in a competitive market.”

Building the Custom ROM

Compiling your custom ROM from the source code is a crucial step that transforms your modifications into a working Android operating system. This process involves several commands and a bit of patience, as the build may take some time depending on your system’s capabilities. Here’s how to effectively compile your custom ROM.Building a custom ROM involves using the Android source code that you’ve downloaded and customized.

Before you can generate the final ROM package, you need to compile the source code using specific commands. This will require a proper setup of your build environment, so ensure that all prerequisites have been completed.

Compiling the Source Code

The compilation process is initiated through the terminal, where you’ll execute a series of commands. It’s essential to follow these steps to ensure successful compilation:Navigate to the root directory of your Android source code in the terminal.

2. Set up the build environment by running

“`bash source build/envsetup.sh “`

3. Choose the target device you’re building for

“`bash lunch “`

4. Start the compilation process with

“`bash make -j$(nproc) “` This command will utilize all available CPU cores for a faster build.Ensure you keep an eye on the terminal output; it will provide real-time feedback on the build status and any issues that may arise.

Troubleshooting Common Build Errors

While building your custom ROM, you may encounter various errors. Here are some common issues and tips to resolve them:

Dependency Errors

If you see messages about missing libraries or dependencies, double-check your installation of necessary packages and libraries. Ensure all prerequisites are installed as specified in the documentation.

Out of Memory

If your system runs out of memory during the build, you might need to reduce the number of jobs you’re running concurrently. Adjust the `-j` parameter in the `make` command to a lower number based on your system’s RAM.

Code Errors

Compilation errors related to the source code usually indicate issues with changes you’ve made. Revisit your modifications, and if necessary, revert them one by one to identify the problematic change.Always refer to forums and community discussions for specific error messages, as the Android development community is active and often shares solutions to similar problems.

Generating the Final ROM Package

Once the build process completes successfully, you’ll need to generate the final ROM package for installation. This process can be summarized in the following steps:

  • Locate the compiled ROM file, usually found in the `out/target/product/ /` directory.
  • The final ROM package is typically named `rom_name.zip`. Make sure to rename this file appropriately if needed.
  • To ensure the ROM package is ready for installation, you may want to create a flashable ZIP that includes necessary scripts for recovery. Use tools like `zip` to package the files correctly.

Always ensure that the generated ROM file is signed appropriately before flashing it onto a device to avoid installation errors.

After generating the ROM package, it’s advisable to test it in a safe environment, like an emulator or a secondary device, to verify stability and functionality before broader deployment.

Testing the Custom ROM

Testing a custom ROM is a vital step in the development process to ensure that the final product is stable, performs well, and provides a positive user experience. In this phase, developers must assess their ROM on various devices to capture a wide range of performance and compatibility metrics, which can significantly influence user satisfaction and adoption rates. A thorough testing process can help identify critical bugs, optimization opportunities, and overall usability issues.

Testing on Various Devices, How to Create a Custom ROM for Android

Testing the custom ROM across different devices is essential due to the diverse hardware and software configurations found in the Android ecosystem. Variability in CPU, RAM, GPU, and screen resolution among devices can lead to performance discrepancies. Consider the following methods to ensure comprehensive testing:

  • Device Variety: Test the ROM on a mix of flagship, mid-range, and budget devices to understand how it performs across different specifications.
  • Emulators: Use Android emulators to simulate various devices and Android versions. This can help identify issues that may not be apparent on physical devices.
  • Real-World Conditions: Test under various scenarios, such as different network conditions (Wi-Fi, 4G, and 5G) and battery levels. This can reveal stability and performance issues that might occur in everyday use.

Conducting Stability and Performance Tests

Stability and performance testing are crucial in ensuring the custom ROM runs smoothly without crashing or lagging. These tests can be grouped into several categories to provide a structured approach:

  • Benchmarking: Utilize benchmarking tools like AnTuTu or Geekbench to quantitatively assess the ROM’s performance against standard metrics such as CPU speed, graphics performance, and memory usage.
  • Stress Testing: Implement stress tests by running multiple applications simultaneously to gauge how the ROM handles heavy workloads. Monitor memory consumption and responsiveness under pressure.
  • Battery Life Testing: Measure battery consumption during regular use and under heavy load. This helps to ensure the ROM is optimized for energy efficiency.

Gathering User Feedback

User feedback is a critical component in the iterative development process of a custom ROM. Engaging with users can reveal insights that might not be apparent through testing alone.Methods to effectively gather user feedback include:

  • Beta Testing: Release a beta version of the ROM to a select group of users who can provide detailed feedback based on their experiences. This helps identify critical issues before the final release.
  • Surveys and Questionnaires: Create structured surveys to ask specific questions about performance, bugs, and features. This can help you quantify user satisfaction and prioritize future updates.
  • Community Engagement: Leverage forums and social media platforms to create a dialogue with users. Encourage them to share their thoughts and experiences, which can guide your development efforts.

Packaging and Distributing the Custom ROM

After successfully building your custom ROM and testing it, the next step is preparing it for public release. This process involves packaging the ROM in a way that makes it easy for users to install while ensuring all necessary components are included. Proper packaging and distribution are crucial for user satisfaction and can also significantly impact the adoption rate of your custom ROM.To package your custom ROM for distribution, follow these steps to ensure it is user-friendly and accessible:

Preparing the Custom ROM for Release

The first step in preparing your custom ROM for public release is to create a suitable installation package. This package should include the ROM files along with any additional resources that users might need. Consider the following components when creating your package:

  • ROM ZIP File: The main file that contains the custom ROM. It should be a flashable ZIP format compatible with recovery tools like TWRP.
  • Installation Instructions: Clear, step-by-step guidelines for users on how to install the ROM, including backup recommendations and prerequisites.
  • Changelog: A detailed log of the changes made in the ROM, including new features, bug fixes, and any known issues.
  • Credits: Acknowledge the contributions of others who helped in the development, such as developers, testers, and community members.
  • Boot Animation and Wallpapers: Optional, but can enhance user experience by providing a unique feel to the ROM.

Creating Installation Instructions

Providing clear installation instructions is essential for ensuring that users can successfully flash your ROM. These instructions should be straightforward and cover various aspects, including:

  • Prerequisites: A list of requirements, such as an unlocked bootloader, custom recovery, and any necessary firmware.
  • Backup: Recommendations for backing up existing data, such as using custom recovery tools or backup apps.
  • Installation Steps: A numbered list of steps, detailing how to flash the ROM, including how to wipe the previous installation if necessary.
  • Troubleshooting Tips: Common issues users might face during installation and how to resolve them.

Sharing the ROM on Forums and ROM Repositories

Once your package is ready, the next step is sharing it with the community. Distributing your custom ROM through forums and repositories increases its visibility and allows users to provide feedback. Here’s how to effectively share your ROM:

  • Select the Right Platforms: Choose popular Android development forums like XDA Developers or specific ROM repositories where users are actively seeking custom ROMs.
  • Create an Engaging Thread: When posting, write a compelling introduction that highlights the unique features of your ROM. Include the ROM name, version number, and a summary of its key features.
  • Attach the Package: Include a direct link to download the ROM ZIP file, as well as the installation instructions and changelog. Use cloud storage services to host the files if needed.
  • Encourage Feedback: Invite users to share their experiences, report bugs, and suggest features. Engage with the community by responding to comments and providing support.

“A well-documented ROM with clear instructions and active support can significantly enhance user experience and community engagement.”

Using these guidelines, you can effectively package and distribute your custom ROM, ensuring that it reaches users in the best possible form and encourages a thriving user community.

Maintaining and Updating the Custom ROM

Keeping your custom ROM up-to-date is crucial for providing users with the latest features, security patches, and overall improved performance. Regular maintenance not only enhances the user experience but also keeps the community engaged and interested in your work. Staying on top of developments in the Android ecosystem ensures that your ROM remains relevant and functional.To maintain and update your custom ROM effectively, you need to follow a systematic approach to incorporate new Android releases, address bugs, and communicate with your user base.

Updating the ROM with New Android Releases

Staying current with Android releases requires a methodical process. It begins with tracking the official Android release schedule and understanding the changes introduced in each version. Here’s how to approach this:

1. Monitor Android Release Announcements

Regularly check for announcements from Google regarding Android version updates. Websites like Android Central and XDA Developers are excellent resources for this information.

2. Download Source Code

Upon the release of a new Android version, download the corresponding source code from the Android Open Source Project (AOSP). Ensure you are using the correct branches that correspond to the version you intend to build.

3. Merge Changes

Integrate the latest changes into your existing codebase. This often involves resolving conflicts between your customizations and the new source code.

4. Testing

Thoroughly test the ROM on multiple devices to ensure compatibility and performance. Consider different hardware configurations and user scenarios to identify potential issues.

5. Release Update

Once testing is complete and any issues have been resolved, prepare your ROM for release. Include changelogs highlighting the new features and improvements.

Handling Bug Fixes and User-Reported Issues

User feedback is invaluable for improving your custom ROM. Addressing bugs promptly can greatly enhance user satisfaction and help build a loyal community. Here are the steps to manage bug fixes effectively:

Establish a Feedback Channel

Set up platforms such as GitHub Issues, forums, or a dedicated Discord server where users can report bugs and suggest features. Ensure the channels are accessible and easy to navigate.

Prioritize Issues

Not all issues are created equal. Prioritize them based on severity and the number of users affected. Critical bugs that hinder usability should be addressed immediately, while minor issues can be resolved in subsequent updates.

Document Bugs and Fixes

Keep a log of reported issues and updates. This helps track the progress of fixes and keeps users informed.

Communicate with Users

Regularly update users on the status of bug fixes. Transparency fosters trust and encourages users to continue providing feedback.

Communicating Updates to Users

Effective communication is key to maintaining a satisfied user base. Here’s how to keep users informed about updates and changes:

1. Changelogs

Always include detailed changelogs with each update. Clearly Artikel new features, bug fixes, and any known issues. This not only informs users but also sets expectations for the update.

2. Social Media and Forums

Utilize platforms like Twitter, Reddit, and dedicated forums to announce updates. Engage with users, answer questions, and gather feedback.

3. Newsletters

Consider sending out periodic newsletters to users who opt-in for updates. This can include tips, tricks, and background on upcoming features.

4. Release Notes

For each significant update, write comprehensive release notes that describe enhancements and provide guidance on how to utilize new features.

5. Community Engagement

Encourage interaction within your community. Organizing Q&A sessions or polls can help gather user input and maintain interest.By systematically managing your custom ROM’s updates, bug fixes, and user communications, you’ll foster a thriving community and enhance the overall experience for your users.

Community Engagement and Support

How to Create a Custom ROM for Android

Engaging with the development community is crucial for the success and longevity of any custom ROM project. A strong community not only aids in troubleshooting issues but also fosters collaboration that can lead to innovative features and improvements. This section highlights the importance of community engagement, establishing a support platform, and the benefits of collaboration with other developers.

Importance of Engaging with the ROM Development Community

Building a vibrant community around your custom ROM can significantly enhance its appeal and usability. Engaging with users and contributors can lead to invaluable feedback and ideas for enhancements. A well-connected community can help address user concerns swiftly and efficiently. Here are several ways to foster community engagement:

  • Participate in online forums and social media groups dedicated to Android development.
  • Host regular Q&A sessions or live streams to address user queries and showcase new features.
  • Encourage user-generated content, such as tutorials or reviews, to share knowledge and experiences.

Creating a Support Platform for Users

A robust support platform is essential for ensuring users can get help when they run into issues. Establishing a dedicated space for users to ask questions, report bugs, and access resources will streamline the support process. Consider incorporating the following elements into your support platform:

  • A comprehensive FAQ section that covers common issues and their solutions.
  • A user forum where users can post questions and share solutions with one another.
  • A ticketing system for tracking user-reported issues and ensuring timely responses from the development team.

Benefits of Collaborating with Other Developers

Collaboration among developers not only enriches your ROM project but can also lead to the creation of unique features that stand out in a crowded market. Working together can result in shared knowledge, resources, and skills that can elevate the quality of the custom ROM. Some benefits of collaboration include:

  • Access to a wider range of expertise, which can improve feature development and bug fixing.
  • Pooling resources to tackle complex problems more efficiently, reducing the workload on individual developers.
  • Creating a sense of community and shared purpose, as developers work towards common goals.

“Collaboration is the heartbeat of innovation.”

By engaging with the community, creating supportive environments for users, and collaborating with fellow developers, you can enhance the overall quality and reputation of your custom ROM. This will not only benefit your project but will also contribute positively to the Android development ecosystem as a whole.

Leave a Reply

Your email address will not be published. Required fields are marked *