SystemServer 启动新增服务APK

简介: SystemServer 启动新增服务APK

平台:


RK3288 + android 7.1


问题:


无法在动画过程启动新增加服务.


LOG输出:


01-01 20:00:18.053 686-713/system_process W/ActivityManager: Unable to start


service Intent { act=action pkg=pkgName }


U=0: not found


分析:


|-- frameworks/base/services/java/com/android/server/SystemServer.java


/**
     * Starts some essential services that are not tangled up in the bootstrap process.
     */
    private void startCoreServices() {
        // Tracks the battery level.  Requires LightService.
        mSystemServiceManager.startService(BatteryService.class);
        // Tracks application usage stats.
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));
        // Tracks whether the updatable WebView is in a ready state and watches for update installs.
        mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
  try{
    //Anson MyService Service
    mSystemServiceManager.startService(MyService.class);
  }catch (Throwable e) {
           reportWtf("starting MyService", e);
  }
    }


新增MyService.java:


|-- frameworks/base/services/core/java/com/android/server/os/MyService.java


public final class MyService extends SystemService implements Handler.Callback {
    private static final String TAG = "MyService";
  private final Context mContext;
  private ServiceThread mHandlerThread;
  private Handler mHandler;
  private Intent serviceIntent = null;
  public MyService(Context context) {
  super(context);
  mContext = context;
  mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_DISPLAY, /*allowTo*/false);
        mHandlerThread.start();
        mHandler = new Handler(mHandlerThread.getLooper(), this);
  }
  @Override
    public boolean handleMessage(android.os.Message msg) {
        switch(msg.what) {
  }
  return true;
  }
  @Override
  public void onStart(){
  Log.d(TAG, "ALog onStart");
  }
  @Override
    public void onBootPhase(int phase) {
        //在AM 初始化完成后执行.
        if (phase == PHASE_ACTIVITY_MANAGER_READY) {
    mHandler.postDelayed(checkService, INTERVAL);
            connectToService();
        }
    }
  final int INTERVAL = 1000;
  private Runnable checkService = new Runnable(){
  public void run(){
    if(!isServiceReady()){
    mHandler.postDelayed(this, INTERVAL);
    connectToService();
    }
  }
  };
  private void connectToService(){
  Log.d(TAG, "ALog connectToService()");
  try{
    if(serviceIntent == null){
    final Intent bindIntent = new Intent(action);
    bindIntent.setComponent(new ComponentName(pkgName, className));
    serviceIntent = bindIntent;
    }
    int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE
      | Context.BIND_AUTO_CREATE;
            //由这里启动服务
    mContext.bindServiceAsUser(serviceIntent, bindConn, flags, android.os.UserHandle.SYSTEM);
  }catch(Exception e){
    e.printStackTrace();
  }
  }
  //ISystemControler mBinder;
  final ServiceConnection bindConn = new ServiceConnection(){
  public void onServiceConnected(ComponentName name, android.os.IBinder service){
    Log.d(TAG, "ALog onServiceConnected");
    mHandler.removeCallbacks(checkService);
    //mBinder = ISystemControler.Stub.asInterface(service);
    publishBinderService(Context.SYSTEMCTRL_SERVICE, service);
  }
  public void onServiceDisconnected(ComponentName name){
    Log.d(TAG, "ALog onServiceDisconnected");
    //mBinder = null;
  }
  };
  private boolean isServiceReady(){
  return null != android.os.ServiceManager.checkService(Context.SYSTEMCTRL_SERVICE);
  }
}
|-- frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private ServiceLookupResult retrieveServiceLocked(Intent service,
            String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
            boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
        ServiceRecord r = null;
        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "retrieveServiceLocked: " + service
                + " type=" + resolvedType + " callingUid=" + callingUid);
        userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
                ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);
        ServiceMap smap = getServiceMap(userId);
        final ComponentName comp = service.getComponent();
        if (comp != null) {
            r = smap.mServicesByName.get(comp);
        }
        if (r == null && !isBindExternal) {
            Intent.FilterComparison filter = new Intent.FilterComparison(service);
            r = smap.mServicesByIntent.get(filter);
        }
        if (r != null && (r.serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0
                && !callingPackage.equals(r.packageName)) {
            // If an external service is running within its own package, other packages
            // should not bind to that instance.
            r = null;
        }
        if (r == null) {
            try {
                // TODO: come back and remove this assumption to triage all services
                ResolveInfo rInfo = AppGlobals.getPackageManager().resolveService(service,
                        resolvedType, ActivityManagerService.STOCK_PM_FLAGS
                                | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                        userId);
                ServiceInfo sInfo =
                    rInfo != null ? rInfo.serviceInfo : null;
                if (sInfo == null) {
                    Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId +
                          ": not found");
                    return null;
                }


问题跟踪:


在MyService.java中加入了服务启动检测, 若不存在, 则在1s 后尝试启动.


在测试过程中发现, 需尝试3次以上才能正常启动.


01-01 20:00:13.042 686-700/system_process D/PackageManager: ALog resolveService Intent { act=action cmp=serviceClass }

   ALog queryIntentServicesInternal by comp(ComponentInfo{pkg/cls})


   ALog getServiceInfo s != null mSettings.isEnabledAndMatchLPr(s.info, flags, userId) = false.


最终LOG定位到 isEnabledAndMatchLPr 函数执行的返回值, 相关代码如下:


//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
    @Override
    public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
        if (!sUserManager.exists(userId)) return null;
  d("resolveService " + intent.toString());
        flags = updateFlagsForResolve(flags, userId, intent);
        List<ResolveInfo> query = queryIntentServicesInternal(intent, resolvedType, flags, userId);
        if (query != null) {
            if (query.size() >= 1) {
                // If there is more than one service with the same priority,
                // just arbitrarily pick the first one.
                return query.get(0);
            }
        }
  d("resolveService could NOT found");
        return null;
    }
private @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
            String resolvedType, int flags, int userId) {
        ...
        if (comp != null) {
    d("queryIntentServicesInternal by comp(" + comp.toString() + ")");
            final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
            final ServiceInfo si = getServiceInfo(comp, flags, userId);
            if (si != null) {
                final ResolveInfo ri = new ResolveInfo();
                ri.serviceInfo = si;
                list.add(ri);
            }
            return list;
        }
        ..
    }
    @Override
    public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
        ...
        synchronized (mPackages) {
            PackageParser.Service s = mServices.mServices.get(component);
            if (DEBUG_PACKAGE_INFO) Log.v(
                TAG, "getServiceInfo " + component + ": " + s);
    d("getServiceInfo flags = " + flags);
    if(s == null){
    d("getServiceInfo s == null");
    }else{
    d("getServiceInfo s != null mSettings.isEnabledAndMatchLPr(s.info, flags, userId) = " + (mSettings.isEnabledAndMatchLPr(s.info, flags, userId)));
    }
            if (s != null && mSettings.isEnabledAndMatchLPr(s.info, flags, userId)) {
                PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                if (ps == null) return null;
                return PackageParser.generateServiceInfo(s, flags, ps.readUserState(userId),
                        userId);
            }
        }
        return null;
    }
//frameworks/base/services/core/java/com/android/server/pm/Settings.java
    boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, int flags, int userId) {
        final PackageSetting ps = mPackages.get(componentInfo.packageName);
        if (ps == null) return false;
        final PackageUserState userState = ps.readUserState(userId);
        return userState.isMatch(componentInfo, flags);
    }
//frameworks/base/core/java/android/content/pm/PackageUserState.java
    /**
     * Test if the given component is considered installed, enabled and a match
     * for the given flags.
     *
     * <p>
     * Expects at least one of {@link PackageManager#MATCH_DIRECT_BOOT_AWARE} and
     * {@link PackageManager#MATCH_DIRECT_BOOT_UNAWARE} are specified in {@code flags}.
     * </p>
     */
    public boolean isMatch(ComponentInfo componentInfo, int flags) {
        if (!isInstalled(flags)) return false;
        if (!isEnabled(componentInfo, flags)) return false;
        if ((flags & MATCH_SYSTEM_ONLY) != 0) {
            if (!componentInfo.applicationInfo.isSystemApp()) {
                return false;
            }
        }
        final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0)
                && !componentInfo.directBootAware;
        final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0)
                && componentInfo.directBootAware;
        return matchesUnaware || matchesAware;
    }


到这里, 意识到跟 flags有点关系, 于是, 打印出了flags的值:


失败:  


ALog getServiceInfo flags = 268960768


成功:


   ALog getServiceInfo flags = 269222912


有什么区别?


268960768 -> #10080400


269222912 -> #100C0400


两个数的16进制相减为 #40000, 这个FLAG的定义如下:


|--frameworks/base/core/java/android/content/pm/PackageManager.java


/**
     * Querying flag: match components which are direct boot <em>unaware</em> in
     * the returned info, regardless of the current user state.
     * <p>
     * When neither {@link #MATCH_DIRECT_BOOT_AWARE} nor
     * {@link #MATCH_DIRECT_BOOT_UNAWARE} are specified, the default behavior is
     * to match only runnable components based on the user state. For example,
     * when a user is started but credentials have not been presented yet, the
     * user is running "locked" and only {@link #MATCH_DIRECT_BOOT_AWARE}
     * components are returned. Once the user credentials have been presented,
     * the user is running "unlocked" and both {@link #MATCH_DIRECT_BOOT_AWARE}
     * and {@link #MATCH_DIRECT_BOOT_UNAWARE} components are returned.
     *
     * @see UserManager#isUserUnlocked()
     */
    public static final int MATCH_DIRECT_BOOT_UNAWARE = 0x00040000;


解决:


在新增加服务APK的AndroidManifest.xml中加入        


android:directBootAware="true"

如:


...
<application
        android:label="@string/app_label"
  android:icon="@mipmap/ic_launcher"
        android:process="system"
  android:directBootAware="true"
        android:supportsRtl="true">
...


相关文章
|
20天前
|
存储 Java Android开发
Android系统 设置第三方应用为默认Launcher实现和原理分析
Android系统 设置第三方应用为默认Launcher实现和原理分析
108 0
|
19天前
|
XML API Android开发
获取正在前台运行的apk 包名
获取正在前台运行的apk 包名
21 5
|
20天前
|
移动开发 Java Unix
Android系统 自动加载自定义JAR文件
Android系统 自动加载自定义JAR文件
60 1
|
Java Android开发 消息中间件
Android系统默认Home应用程序(Launcher)的启动过程源代码分析
转自 :http://blog.csdn.net/luoshengyang/article/details/6767736    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应用程序就是Launcher了,本文将详细分析Laun
2142 0
|
存储 Android开发
【Android 逆向】启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区 | 配置清单文件 | 启动 DEX 文件中的组件 | 执行结果 )(二)
【Android 逆向】启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区 | 配置清单文件 | 启动 DEX 文件中的组件 | 执行结果 )(二)
130 0
【Android 逆向】启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区 | 配置清单文件 | 启动 DEX 文件中的组件 | 执行结果 )(二)
|
存储 Android开发
【Android 逆向】启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区 | 配置清单文件 | 启动 DEX 文件中的组件 | 执行结果 )(一)
【Android 逆向】启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区 | 配置清单文件 | 启动 DEX 文件中的组件 | 执行结果 )(一)
208 0
【Android 逆向】启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区 | 配置清单文件 | 启动 DEX 文件中的组件 | 执行结果 )(一)
|
Android开发
【Android 插件化】VirtualApp 接入 ( 安装 APK 插件应用 | 启动插件 APK 应用 | MainActivity 安装启动插件完整代码 )
【Android 插件化】VirtualApp 接入 ( 安装 APK 插件应用 | 启动插件 APK 应用 | MainActivity 安装启动插件完整代码 )
394 0
|
Android开发
Android插件化开发之运行未安装apk的activity(2)
Android插件化开发之运行未安装apk的activity(2)
122 0
Android插件化开发之运行未安装apk的activity(2)
|
Android开发
Android插件化开发之运行未安装apk的activity(1)
Android插件化开发之运行未安装apk的activity(1)
292 0
Android插件化开发之运行未安装apk的activity(1)