Fastboot HAL module implemetation

I was trying to have “fastboot format userdata" work in user space fastboot

but some how I “adb reboot fastboot" and device go to user space fastboot but always fail to perform “fastboot format userdata"

looking into the source, there are 2 things need to be done

  1. Fastboot HAL add to PRODUCT_PACKAGES
  2. implement the Fastboot HAL module

https://android-review.googlesource.com/c/device/google/muskie/+/1473229 add android.hardware.fastboot@1.0-impl-mock

https://android-review.googlesource.com/c/platform/hardware/libhardware/+/1473557 Add fastboot.h for Fastboot OEM HAL

https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1473621 implement Fastboot OEM HAL of getPartitionType

https://android-review.googlesource.com/c/platform/build/+/1473622 add owenwen to vendor module list

and I create vendor/owenwen/fastboot for my fastboot module

Android.bp

cc_library_shared {

    name: "fastboot.default",

    //recovery_available: true, // not work, this setting won't install the module into recovery image
    recovery: true,

    relative_install_path: "hw",

    include_dirs: [
        "hardware/libhardware/include",
    ],

    srcs: ["Fastboot.cpp"],

    owner: "owenwen",
}

Fastboot.cpp

#include <hardware/hardware.h>
#include <hardware/fastboot.h>
#include <cstring>

#define USERDATA "userdata"

static struct hw_module_methods_t fastboot_module_methods = {
        .open = NULL,
};

/* refer hardware/interfaces/fastboot/1.0/types.hal for the return value of this function
 * 0: EXT4
 * 1: F2FS
 * 2: RAW
 */
static int module_getPartitionType(fastboot_module_t* /*module*/, const char* partitionName) {
        if (std::strncmp(partitionName, USERDATA, std::strlen(USERDATA)) == 0) {
                return 0;
        } else {
                return 2;
        }
}

fastboot_module_t HAL_MODULE_INFO_SYM = {
        .common = {
                .tag = HARDWARE_MODULE_TAG,
                .version_major = 1,
                .version_minor = 0,
                .id = FASTBOOT_MODULE_ID,
                .name = "Fastboot HAL Module",
                .author = "Owen Wen",
                .methods = &fastboot_module_methods,
        },
        .getPartitionType = module_getPartitionType,
};

How to remove notify in Android O, customize AOSP

https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java;drc=b61408add5839a01f40809fc05608af244c0e47d;l=5296

There is no config to turn on/off the notification, so can only customize the AOSP source code

    private boolean isBlocked(NotificationRecord r) {
        final String pkg = r.sbn.getPackageName();
        final int callingUid = r.sbn.getUid();
        return mPreferencesHelper.isGroupBlocked(pkg, callingUid, r.getChannel().getGroup())
                || mPreferencesHelper.getImportance(pkg, callingUid)
                == NotificationManager.IMPORTANCE_NONE
                || r.getImportance() == NotificationManager.IMPORTANCE_NONE;
    }

How to change Android PiP default location programmatically

refer to below commit, this setting help to change the default location of PIP window

please refer to  https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/Gravity.java;l=45 to find out the value you need

e.g. Gravity.TOP | Gravity.RIGHT is 0x35

commit 06868c37df46c0c973a96a0a25b1f301384db4be
Author: Winson <winsonc@google.com>
Date:   Wed Oct 12 21:08:18 2016 -0700

    Changing initial PIP bounds specifications.
    
    - Change from a absolute bounds to a size, gravity and inset to
      allow easier tweaking of initial pinned stack bounds.
    
    Test: android.server.cts.ActivityManagerPinnedStackTests
    Test: #testPinnedStackDefaultBounds
    Test: #testPinnedStackMovementBounds
    
    Change-Id: I82a102bbd2d83259c6c84915071d1a16728e3aa7

diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c40436a5bda..30dcfb081d8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2482,8 +2482,17 @@
          -->
     <integer name="config_navBarOpacityMode">0</integer>
 
-    <!-- Default bounds [left top right bottom] on screen for picture-in-picture windows. -->
-    <string translatable="false" name="config_defaultPictureInPictureBounds">"0 0 100 100"</string>
+    <!-- Default insets [LEFT/RIGHTxTOP/BOTTOM] from the screen edge for picture-in-picture windows.
+         These values are in DPs and will be converted to pixel sizes internally. -->
+    <string translatable="false" name="config_defaultPictureInPictureScreenEdgeInsets">10x10</string>
+
+    <!-- Max default size [WIDTHxHEIGHT] on screen for picture-in-picture windows to fit inside.
+         These values are in DPs and will be converted to pixel sizes internally. -->
+    <string translatable="false" name="config_defaultPictureInPictureSize">216x135</string>
+
+    <!-- The default gravity for the picture-in-picture window.
+         Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT -->
+    <integer name="config_defaultPictureInPictureGravity">0x55</integer>

Android sepolicy not work

I got avc message as below

avc: denied { write } for name="xxxx" dev="mmcblk0p18" ino=131138 scontext=u:r:platform_app:s0:c512,c768 tcontext=u:object_r:xxxx_data_file:s0 tclass=dir permissive=0 app=com.xxxx.xxxx

then I add sepolicy

allow platform_app xxxx_data_file:dir { write };

but still not work

after days of google, root cause is MLS

refer code here https://cs.android.com/android/platform/superproject/+/master:external/selinux/libselinux/src/android/android_platform.c;l=775;bpv=0;bpt=1

and here

https://cs.android.com/android/platform/superproject/+/master:system/sepolicy/private/seapp_contexts;l=157

platform_app using MLS LEVEL_FROM “user"

user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user

USER default category is c512,c768

	case LEVELFROM_USER:
		snprintf(level, sizeof level, "s0:c%u,c%u",
			 512 + (userid & 0xff),
			 768 + (userid>>8 & 0xff));
		break;

so the solution is

+typeattribute platform_app mlstrustedsubject

and in my case, the folder /data/xxx is create in init.rc, it doesn’t belongs to a specific user, so it make sense set my platform_app as mlstrustedsubject then platform_app can ignore the MLS setting

Android mDNS change host name from Android.local to your customized name

Android.local is defined here

https://cs.android.com/android/platform/superproject/+/master:external/mdnsresponder/mDNSPosix/mDNSPosix.c;l=489

 481 // This gets the current hostname, truncating it at the first dot if necessary
 482 mDNSlocal void GetUserSpecifiedRFC1034ComputerName(domainlabel *const namelabel)
 483 >---{
 484 >---int len = 0;
 485 #ifndef __ANDROID__
 486 >---gethostname((char *)(&namelabel->c[1]), MAX_DOMAIN_LABEL);
 487 #else
 488 >---// use an appropriate default label rather than the linux default of 'localhost'
 489 >---strncpy(&namelabel->c[1], "Android", MAX_DOMAIN_LABEL);
 490 #endif
 491 >---while (len < MAX_DOMAIN_LABEL && namelabel->c[len+1] && namelabel->c[len+1] != '.') len++;
 492 >---namelabel->c[0] = len;
 493 >---}

look into line 489, here is the reason why change the argument host in function DNSServiceRegister didn’t take effect

build android 10 with 8G ram laptop

you may encounter problem when building android with low ram machine

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.base/java.util.Arrays.copyOf(Arrays.java:3793)
at com.intellij.util.ArrayUtil.realloc(ArrayUtil.java:84)
at com.intellij.lang.impl.TokenSequence$Builder.resizeLexemes(TokenSequence.java:114)
at com.intellij.lang.impl.TokenSequence$Builder.performLexing(TokenSequence.java:77)
at com.intellij.lang.impl.PsiBuilderImpl.performLexing(PsiBuilderImpl.java:187)
at com.intellij.lang.impl.PsiBuilderImpl.(PsiBuilderImpl.java:160)
at com.intellij.lang.impl.PsiBuilderImpl.(PsiBuilderImpl.java:114)
at com.intellij.lang.impl.PsiBuilderFactoryImpl.createBuilder(PsiBuilderFactoryImpl.java:37)
at com.intellij.lang.java.parser.JavaParserUtil.createBuilder(JavaParserUtil.java:152)
at com.intellij.psi.impl.source.JavaFileElementType.parseContents(JavaFileElementType.java:80)
at com.intellij.psi.impl.source.tree.LazyParseableElement.lambda$ensureParsed$0(LazyParseableElement.java:189)
at com.intellij.psi.impl.source.tree.LazyParseableElement$$Lambda$217/0x0000000100515040.run(Unknown Source)
at com.intellij.psi.impl.DebugUtil.performPsiModification(DebugUtil.java:564)
at com.intellij.psi.impl.source.tree.LazyParseableElement.ensureParsed(LazyParseableElement.java:188)
at com.intellij.psi.impl.source.tree.LazyParseableElement.getFirstChildNode(LazyParseableElement.java:237)
at com.intellij.psi.impl.source.tree.CompositeElement.countChildren(CompositeElement.java:432)
at com.intellij.psi.impl.source.tree.CompositeElement.getChildrenAsPsiElements(CompositeElement.java:394)
at com.intellij.psi.impl.source.PsiJavaFileBaseImpl.getClasses(PsiJavaFileBaseImpl.java:66)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCliJavaFileManagerImpl$Companion.findClassInPsiFile(KotlinCliJavaFileManagerImpl.kt:263)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCliJavaFileManagerImpl$Companion.access$findClassInPsiFile(KotlinCliJavaFileManagerImpl.kt:259)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCliJavaFileManagerImpl.findPsiClassInVirtualFile(KotlinCliJavaFileManagerImpl.kt:229)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCliJavaFileManagerImpl.findClass(KotlinCliJavaFileManagerImpl.kt:124)
at org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade$CliFinder.findClass(KotlinJavaPsiFacade.java:363)
at org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade.findClass(KotlinJavaPsiFacade.java:123)
at org.jetbrains.kotlin.load.java.JavaClassFinderImpl.findClass(JavaClassFinderImpl.kt:36)
at org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageScope$classes$1.invoke(LazyJavaPackageScope.kt:76)
at org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageScope$classes$1.invoke(LazyJavaPackageScope.kt:42)
at org.jetbrains.kotlin.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:512)
at org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageScope.findClassifier(LazyJavaPackageScope.kt:142)
at org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageScope.getContributedClassifier(LazyJavaPackageScope.kt:132)
at org.jetbrains.kotlin.load.java.lazy.descriptors.JvmPackageScope.getContributedClassifier(JvmPackageScope.kt:52)
at org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope.getContributedClassifier(ChainedMemberScope.kt:33)

have a check for your build machine

java -XshowSettings 2>&1  | grep Heap

https://cs.android.com/android/platform/superproject/+/master:build/soong/java/config/config.go;l=64?q=build%2Fsoong%2Fjava%2Fconfig%2Fconfig.go

change this line from 2048 to 1024

pctx.StaticVariable("JavacHeapSize", "1024M")
android metalava use a lot of memory

 

or you can also try adjust linux memory setting

cat /proc/sys/vm/overcommit_ratio
cat /proc/sys/vm/overcommit_memory

 

But I still fail to build AOSP and seems adding swap has no help for java max heap size

refer: https://stackoverflow.com/a/34858395/1117177


Do. Not. Do this.

Get more memory.

Java and Swap Do. Not. Mix. Java and Swap are like "Crossing the Streams" Bad.

Part of the Java heap will be swapped out, then Java will GC, which will thrash the box terribly, and still part of the heap will be swapped out, and Java will GC again.

Rinse and repeat until you finally kill -9 Weblogic.

Get more memory, or do without. Swap is not an option.

Addenda:

You machine has "Virtual Memory" (VM). By adding swap, you extend that VM. When you have more VM than actual memory, then the machine will "swap out" inactive memory pages to the swap space, and then "swap in" pages that want to be active from swap space in to RAM. If you have a bunch of idle processes that rarely need time, this isn't super terrible.

But Java magnifies the problem. When you run out of physical RAM, some of that RAM is swapped out to disk. When some of that RAM is Java heap, then you have a big problem when the garbage collector kicks in. Because, in general, the GC touches every page of the heap. That means that all of the heaps pages need to be "active", and thus, "swapped in".

But if they don't fit, then you have a problem like the 8 puzzle. Where you're shifting memory in and out from disk. This is called thrashing.

A swapped JVM heap that is GC is the text book case of worst case thrashing.

The machine is letting you allocate the extra memory because it thinks you have more, since your Virtual Memory (physical RAM + swap) is greater

 

How to install google play on AOSP emulator

I want to know how google play install an app and why no dialog popup when google play install an app

currently PackageInstallActivity dialog will pop up even no any permission is required by the app which fdroid is installing

  1. download Gapps from https://opengapps.org/, e.g. I download open_gapps-arm64-9.0-stock-20191213
  2. mkdir -p device/xxx/apps
  3. add file device device/xxx/apps/Android.mk and edit as below
    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)
    LOCAL_MODULE := Phonesky
    LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
    LOCAL_CERTIFICATE := PRESIGNED
    LOCAL_PRIVILEGED_MODULE := true
    LOCAL_MODULE_CLASS := APPS
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
    LOCAL_DEX_PREOPT := true
    include $(BUILD_PREBUILT)

    include $(CLEAR_VARS)
    LOCAL_MODULE := GoogleServicesFramework
    LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
    LOCAL_CERTIFICATE := PRESIGNED
    LOCAL_PRIVILEGED_MODULE := true
    LOCAL_MODULE_CLASS := APPS
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
    LOCAL_DEX_PREOPT := true
    include $(BUILD_PREBUILT)

    include $(CLEAR_VARS)
    LOCAL_MODULE := PrebuiltGmsCore
    LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
    LOCAL_CERTIFICATE := PRESIGNED
    LOCAL_PRIVILEGED_MODULE := true
    LOCAL_MODULE_CLASS := APPS
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
    LOCAL_DEX_PREOPT := true
    include $(BUILD_PREBUILT)

    include $(CLEAR_VARS)
    LOCAL_MODULE := GmsCoreSetupPrebuilt
    LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
    LOCAL_CERTIFICATE := PRESIGNED
    LOCAL_PRIVILEGED_MODULE := true
    LOCAL_MODULE_CLASS := APPS
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
    LOCAL_DEX_PREOPT := true
    include $(BUILD_PREBUILT)

  4. copy below 4 apps to device/xxx/apps/
    these 4 apps are required for login and install apps from google play
    Phonesky.apk, GoogleServicesFramework.apk, PrebuiltGmsCorePi.apk, GmsCoreSetupPrebuilt.apk
  5. update device/xxx/xxx_common.mk as below
    PRODUCT_PACKAGES += \
    libg1 \
    libhantro \
    – libcodec
    + libcodec \
    + Phonesky \
    + GoogleServicesFramework \
    + PrebuiltGmsCorePi \
    + GmsCoreSetupPrebuilt
  6. make and flash images to your device
  7. boot to Android OS and open google play, then you will see below messages
    0
  8. please read the part for custom rom users
    open https://g.co/AndroidDeviceRegistration
  9. adb shell ‘sqlite3 /data/data/com.google.android.gsf/databases/gservices.db “select * from main where name = \"android_id\";"‘
  10. 0
  11. and register your Google Service Framework Android ID
    you should can login google play after about 20 mins(according to my experience)

disable proximity sensor

In Android 10, there is a feature “Sensor off" which is to improve the privacy for you

your android device will become deaf and blind when “Sensor off" turned on, android device cannot hear the voice, cannot open camera, cannot detect proximity, etc…

The framework API is here https://cs.android.com/android/platform/superproject/+/master:out/soong/.intermediates/frameworks/base/framework-minus-apex/android_common/xref28/srcjars.xref/frameworks/base/core/java/android/hardware/ISensorPrivacyManager.java;l=222;bpv=1;bpt=1

and only Application signed with platform key can access this API

if app not signed with platform key call this function, it will crash and see below error message

Accessing hidden method Landroid/hardware/SensorPrivacyManager;-&amp;amp;amp;amp;amp;gt;setSensorPrivacy(Z)V (blacklist, linking, denied)

 

below are some key point of code for a sample app which has ability to enable/disable sensor off

Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := samples

# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_PACKAGE_NAME := demo

LOCAL_SDK_VERSION := current

LOCAL_CERTIFICATE := platform

LOCAL_DEX_PREOPT := false

LOCAL_PRODUCT_MODULE := true

include $(BUILD_PACKAGE)

SensorPrivacyManager.java this file help you build pass since android.hardware.SensorPrivacyManager is not exist in SDK

package android.hardware;

public class SensorPrivacyManager {
    public void setSensorPrivacy(boolean enable) {
    }
}

HelloActivity.java

package com.idtech.SensorDisableDemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.util.Log;
import android.widget.Button;
import android.hardware.SensorPrivacyManager;

/**
 * A minimal "Hello, World!" application.
 */
public class HelloActivity extends Activity {
    private static final String TAG = "(Idtech)";
    private static final java.lang.String DESCRIPTOR = "sensor_privacy";
    private static final int FUNC_SUSPEND = 1;
    private static final int FUNC_RESUME = 2;
    Button mButton;
    Button mButton2;
    private SensorPrivacyManager mSensorPrivacyManager;
    /**
     * Called with the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Set the layout for this activity.  You can find it
        // in res/layout/hello_activity.xml
        View view = getLayoutInflater().inflate(R.layout.hello_activity, null);
        setContentView(view);
        mButton = (Button)findViewById(R.id.Button);
        mButton2 = (Button)findViewById(R.id.Button2);

        Log.i(TAG, "Client oncreate ");
        // Get an instance of Sensor Privacy Service.
        mSensorPrivacyManager = (SensorPrivacyManager)getSystemService(DESCRIPTOR);
        mButton.setOnClickListener(new Button.OnClickListener(){
            @Override
            public void onClick(View v) {
                mSensorPrivacyManager.setSensorPrivacy(true);
            }
        });
        mButton2.setOnClickListener(new Button.OnClickListener(){
            @Override
            public void onClick(View v) {
                mSensorPrivacyManager.setSensorPrivacy(false);
            }
        });
    }
}

 

 

 

 

Android fail to adjust audio volume

actually, it’s AOSP design

volume is either max or muted when HDMI out

https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/audio/AudioService.java;l=507?q=mFixedVolumeDevices&ss=android

    // Devices for which the volume is fixed (volume is either max or muted)
    Set<Integer> mFixedVolumeDevices = new HashSet<>(Arrays.asList(
            AudioSystem.DEVICE_OUT_HDMI,
            AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
            AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
            AudioSystem.DEVICE_OUT_HDMI_ARC,
            AudioSystem.DEVICE_OUT_SPDIF,
            AudioSystem.DEVICE_OUT_AUX_LINE));