adb shell top 在前台显示我的应用程序,但实际上它在后台

adb shell top shows my application in foreground but actually its in background

我有 Android 应用程序,其中包含一些绑定到某个进程的服务。

我发现 adb shell top -n 1 returns:

PID PR CPU% S  #THR     VSS     RSS PCY UID      Name
31647  0   1% S    70 1733640K  98960K  bg u0_a132  com.my.app.dev
31727  0   1% S    29 1523892K  62924K  fg u0_a132  com.my.app.dev:myService

即使我的应用程序停留在后台,为什么 top PCY 告诉 'fg' a.e。前景?

有人可以阐明这个问题吗?

这是我的 Manifest.xml:

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
          package="com.my.app.dev" 
          android:versionName="4.0.1.6700000"
          android:versionCode="5033" >
    
    <uses-sdk android:minSdkVersion="10"
              android:targetSdkVersion="16" />
    
    
    
    
        
    <application android:icon="@drawable/icon" 
                 android:label="@string/config_app_name" 
                 android:theme="@style/Theme.NoActionBarAppCompat" 
                 android:name="com.my.app.Mine" > 
                 
        <!-- we would prefer the launchMode to be standard, but it causes a lot of problems. -->
        <activity android:name="com.my.ui.main.MineApp" 
                  android:label="@string/config_app_name"
                  android:launchMode="singleTask" 
                  android:clearTaskOnLaunch="true" 
                  android:theme="@style/Theme.Translucent.NoActionBarAppCompat" >

            <intent-filter>      
                <category android:name="android.intent.category.DEFAULT" />
                <action android:name="mine.action.HomeActivity" />
                
                <category android:name="android.intent.category.LAUNCHER" />
                <action android:name="android.intent.action.MAIN" />
            </intent-filter>
        </activity>
        
        
        
        <meta-data android:name="com.google.android.maps.v2.API_KEY"
                   android:value="xxxxxx" />
        
        <meta-data android:name="com.google.android.gms.version" 
                   android:value="@integer/google_play_services_version" />
        
        
        
        <uses-library android:name="com.google.android.maps" /> 
        
        
    
        
        <service android:name="com.my.engine.logic.EngineService" 
                 android:process=":myService">
            <intent-filter>
                
                <action android:name="com_my_RemoteService" />
                <action android:name="com_my_EngineService" />
            </intent-filter>
        </service>
        
        

        
                
        <receiver 
          android:name="com.my.engine.analytics.ReferrerReceiver" 
          android:exported="true" android:process=":myService">
            <intent-filter>
                <action 
              android:name="com.android.vending.INSTALL_REFERRER"/>
            </intent-filter>
        </receiver>
        
        <receiver 
              android:name="com.my.engine.BootBroadcastReceiver" 
              android:process=":myService">
            <intent-filter>
                <action 
android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>

        <receiver 
             android:name="com.my.engine.util.MineWatcherReceiver" 
             android:process=":myServiceWatcher">
            <intent-filter>
                <action
       android:name="android.intent.action.ACTION_POWER_CONNECTED" />
                <action   
       android:name="android.intent.action.BATTERY_OKAY" />
                <action 
       android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <action 
       android:name="android.intent.action.USER_PRESENT" />
            </intent-filter>
        </receiver>
    
        <receiver 
           android:name="com.my.engine.logic.InitServiceReceiver" 
           android:exported="true" android:process=":myService">
            <intent-filter>
                <action android:name="initServiceCheck"/>
            </intent-filter>
        </receiver>

        <receiver 
            android:name="com.my.engine.logic.UpdateCounterReceiver" 
            android:exported="true" android:process=":myService">
            <intent-filter>
                <action android:name="updateCustomCounter"/>
            </intent-filter>
        </receiver>
        
        <receiver 
         android:name="com.my.engine.logic.PackageChangeReceiver" 
         android:process=":myService">
            <intent-filter>
                <action  
              android:name="android.intent.action.PACKAGE_ADDED"/>
                <action 
              android:name="android.intent.action.PACKAGE_REPLACED"/>
                <action 
              android:name="android.intent.action.PACKAGE_REMOVED"/>
                <action 
              android:name="android.intent.action.PACKAGE_INSTALL"/>
                <data android:scheme="package"/>
            </intent-filter>
        </receiver>
        
        <!-- for notification try next action -->
        <service android:name="com.my.notifications.actions.TryNextNotificationActionService" />
        
        <receiver android:name="com.my.ui.base.EulaReminderReceiver">
            <intent-filter>
                <action android:name="eulaReminderAction" />         
            </intent-filter>
        </receiver>
        
        <receiver android:name="com.my.ui.base.MineGuiBroadcastReceiver">
            <intent-filter>
                <action android:name="finishStoppedActivities" /> 
            </intent-filter>
        </receiver>
        
        <service android:name="com.my.infra.motion.ActivityRecognitionService"
                 android:label="ActivityRecognitionService"
                 android:exported="true"
                 android:enabled="true"
                 android:process=":myService">
        </service>
        
    </application>
    
</manifest> 

编辑 1

我什至停止了来自设置的通知,但仍然 process=":myService 在前台

编辑 2

来自 sources:

if (p == SP_BACKGROUND)
        strcpy(proc->policy, "bg");
    else if (p == SP_FOREGROUND)
        strcpy(proc->policy, "fg");
    else
        strcpy(proc->policy, "er");

来自 Answer in other question:

Mostly-uneducated-somewhat-random-stab-in-the-dark for PCY --

PCY -- Policy -- Determines how an app should be treated by Android's memory manager

FG -- Foreground -- Process is considered a foreground process and should not be killed to free memory

BG -- Background -- Process is considered a background process (not actively running in foreground and may be killed to free memory)

PCY代表scheduling policy。该列中的 fg 表示该进程的优先级高于 bg。这并不意味着该进程在前台运行。

详细说明 Alex P. 的回答:

我相信 PCY 列指的是进程分配给的 cgroup。 Android 定义了两个 cgroup 组,SP_FOREGROUNDSP_BACKGROUNDSP_BACKGROUND 的实际 cgroup 名称是 bg_non_interactive。这些组在 top 中分别用缩写 fgbg 表示。

您可以在整个框架中找到对这些内容的引用,最显着的是 Process.javaIPCThreadState.cppandroid_util_Process.cpp 中与 Linux /proc 文件系统来管理 运行 进程的各个方面。根据这些文件中的源代码评论,似乎前台 cgroup 中的所有线程都安排了 CPU 的 'normal' 份额,而后台 cgroup 中的线程已安排 'reduced' 份额。

关于正常和减少的定义,this 博客指出 SP_BACKGROUND 线程被限制为 5% CPU 使用率。您可以通过在 运行 设备上查看 /dev/cpuctl/bg_non_interactive/cpu.shares 来确认这一点。在我的 Nexus 5 运行 AOSP 5.1 上,我得到:

root@hammerhead:/ # cat /dev/cpuctl/bg_non_interactive/cpu.shares              
52
root@hammerhead:/ #

这里的52是指cgroup线程允许的'CPU shares'个数,最多1024个。因此,在这种情况下,bg_non_interactive 个线程确实允许组中所有线程的最大 ~5% CPU 使用总量。

无论如何,很明显,此上下文中的前景和背景与 Android 的 Activity lifecycle 以及前景和背景应用程序的概念关系不大。这就是 Android 利用 Linux 的 cgroups 功能的简单方式。