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">

...

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值