我们如何识别窗口的所有者?

时间:2017-07-05 14:51:46

标签: android

假设我们有一个Android设备,并且在该设备上有1个以上的应用程序能够创建自己的浮动窗口(例如,持有SYSTEM_ALERT_WINDOW权限)。另外,当然,可以有其他窗口不一定是独立浮动的(SpinnerDialog等等。所有窗口都通过WindowManager创建自己的窗口,仅用于在现有活动上显示)。

鉴于我从开发人员工具知道窗口内的像素坐标,我如何确定创建包含该像素的窗口的进程或应用程序? IOW,我怎样才能找出应该为某个窗口的存在负责的人呢?

我认为也许adb shell dumpsys window会有这些信息,但如果确实如此,我就没有看到它。

请注意,我很乐意找到涉及开发工具的解决方案。我希望没有特殊权限,在运行时确定这些信息是困难的或不可能的。

4 个答案:

答案 0 :(得分:2)

运行此命令adb shell dumpsys input会给我以下输出:

[...bunch of stuff...]

    6: name='Window{5e9310c u0 com.example.overlayservice/com.example.overlayservice.MainActivity}', 
    displayId=0, paused=false, hasFocus=true, hasWallpaper=false,
    visible=true, canReceiveKeys=true, flags=0x81810120, type=0x00000001, layer=21010, 
    frame=[0,0][1440,2560], scale=1.000000, touchableRegion=[0,0][1440,2560], 
    inputFeatures=0x00000000, ownerPid=4086, ownerUid=10083, dispatchingTimeout=5000.000ms

[...bunch more stuff..]

由于我支持这个,我知道应用程序是" Overlay Service"它只是显示一个系统窗口。 "框架"信息将绑定像素和" ownerUid"会提供有关所有者的更多信息。 (我认为这个命令不仅仅是伪装的dumpsys window命令,而且不适合你。)

虽然它并不是这个应用程序中的一个像素"映射,假设您在设备上看到相同的信息,这种技术可以帮助减少目标。

<强>交替

如果您有权访问设备或在模拟器上,以下是更直接的方法。

根据Input Dispatcher State类别下的dumpsys文档,

  

输入调度员状态

     

InputDispatcher负责向应用程序发送输入事件。如下面的示例输出所示,其状态转储显示有关正在触摸的窗口,输入队列的状态,ANR是否正在进行等的信息。

进一步阅读:

  

触摸触摸屏并同时运行dumpsys后,TouchStates行正确识别您正在触摸的窗口。

具体来说,字符串&#34; TouchStates:...&#34;将在我们运行dumpsys时确定我们正在触摸的窗口。

因此,我们应该能够运行dumpsys input并查找字符串TouchStates并打印以下几行以标识窗口。这是我的Windows命令行:

timeout 3 & adb shell dumpsys input | grep TouchStates -A 5

这是输出,将Window{e3cd95d u0 com.example.overlayservice/com.example.overlayservice.MainActivity}'标识为被触摸的窗口。

  

TouchStatesByDisplay:       0:down = true,split = true,deviceId = 0,source = 0x00001002         视窗:           0:name =&#39; Window {e3cd95d u0 com.example.overlayservice / com.example.overlayservice.MainActivity}&#39;,pointerIds = 0x80000000,targetFlags = 0x107     视窗:       0:name =&#39; Window {ef28ce5 u0 NavigationBar}&#39;,displayId = 0,paused = false,hasFocus = false,hasWallpaper = false,visible = true,canReceiveKeys = false,flags = 0x21840068   ,type = 0x000007e3,layer = 231000,frame = [0,1794] [1080,1920],scale = 1.000000,touchableRegion = [0,1794] [1080,1920],inputFeatures = 0x00000000,ownerPid = 1632,ownerUid =   10027,dispatchingTimeout = 5000.000ms

如果没有触摸任何窗口,您将看到TouchStates: <no displays touched>

答案 1 :(得分:1)

来自adb shell dumpsys window

Window#3 Window {41b85d98 u10 com.example.app}:     mDisplayId = 0 mSession = Session {41bc2e38 10536:u10a10030} mClient=android.os.BinderProxy@41b064c0     mOwnerUid = 1010030 mShowToOwnerOnly = true package = com.example.app appop = SYSTEM_ALERT_WINDOW     mAttrs = WM.LayoutParams {(0,0)(395x110)gr =#55 sim =#20 ty = 2003 fl =#20008 fmt = -3}     要求w = 395 h = 110 mLayoutSeq = 1200     mHasSurface = true mShownFrame = [885.0,642.0] [1280.0,752.0] isReadyForDisplay()= true     WindowStateAnimator {41d4d2a8}:       表面:显示=真实层= 91000 alpha = 1.0 rect =(885.0,642.0)395.0 x 110.0

在我看来,mShownFrame变量保存了确定窗口是否包含像素所需的数据。

答案 2 :(得分:1)

此选项如何:adb shell dumpsys window windows visible-apps

它打印可见窗口列表,每个窗口包含以下字段: mOwnerUidpackagemFramemShownPositionmIsFloatingLayer等。

答案 3 :(得分:0)

  

我希望在运行时确定这些信息   没有特权的困难或不可能

最新的Android版本被大量锁定,以防止恶意软件欺骗&#34;信任&#34;网上银行应用程序等应用程序。

即使知道通过/proc文件系统正在运行的其他进程现在也受到限制,因此您似乎不可能在不使用平台的情况下知道像素所有权(这将是获得相同的后门/proc的信息将公开当前的前台进程。)