IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Service的启动过程(源码分析) -> 正文阅读

[移动开发]Service的启动过程(源码分析)

基于Android11

要启动Service,我们会调用startService方法,它的实现在ContextWrapper中,代码如下所示:
frameworks/base/core/java/android/content/ContextWrapper.java

public class ContextWrapper extends Context {
    Context mBase;
...
  @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }
...    
}

在startService方法中会调用mBase的startService方法,Context类型的mBase对象具体指的是什么呢?

ActivityThread启动Activity时会调用如下代码创建Activity的上下文环境。
frameworks/base/core/java/android/app/ActivityThread.java

/**  Core implementation of activity launch. */
3312      private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
3313          ActivityInfo aInfo = r.activityInfo;
3314          if (r.packageInfo == null) {
3315              r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
3316                      Context.CONTEXT_INCLUDE_CODE);
3317          }
3318  
3319          ComponentName component = r.intent.getComponent();
3320          if (component == null) {
3321              component = r.intent.resolveActivity(
3322                  mInitialApplication.getPackageManager());
3323              r.intent.setComponent(component);
3324          }
3325  
3326          if (r.activityInfo.targetActivity != null) {
3327              component = new ComponentName(r.activityInfo.packageName,
3328                      r.activityInfo.targetActivity);
3329          }
3330  
3331          ContextImpl appContext = createBaseContextForActivity(r);
3332          Activity activity = null;
3333          try {
3334              java.lang.ClassLoader cl = appContext.getClassLoader();
3335              activity = mInstrumentation.newActivity(
3336                      cl, component.getClassName(), r.intent);
3337              StrictMode.incrementExpectedActivityCount(activity.getClass());
3338              r.intent.setExtrasClassLoader(cl);
3339              r.intent.prepareToEnterProcess();
3340              if (r.state != null) {
3341                  r.state.setClassLoader(cl);
3342              }
3343          } catch (Exception e) {
3344              if (!mInstrumentation.onException(activity, e)) {
3345                  throw new RuntimeException(
3346                      "Unable to instantiate activity " + component
3347                      + ": " + e.toString(), e);
3348              }
3349          }
3350  
3351          try {
3352              Application app = r.packageInfo.makeApplication(false, mInstrumentation);
3353  
3354              if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
3355              if (localLOGV) Slog.v(
3356                      TAG, r + ": app=" + app
3357                      + ", appName=" + app.getPackageName()
3358                      + ", pkg=" + r.packageInfo.getPackageName()
3359                      + ", comp=" + r.intent.getComponent().toShortString()
3360                      + ", dir=" + r.packageInfo.getAppDir());
3361  
3362              if (activity != null) {
3363                  CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
3364                  Configuration config = new Configuration(mCompatConfiguration);
3365                  if (r.overrideConfig != null) {
3366                      config.updateFrom(r.overrideConfig);
3367                  }
3368                  if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
3369                          + r.activityInfo.name + " with config " + config);
3370                  Window window = null;
3371                  if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
3372                      window = r.mPendingRemoveWindow;
3373                      r.mPendingRemoveWindow = null;
3374                      r.mPendingRemoveWindowManager = null;
3375                  }
3376  
3377                  // Activity resources must be initialized with the same loaders as the
3378                  // application context.
3379                  appContext.getResources().addLoaders(
3380                          app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
3381  
3382                  appContext.setOuterContext(activity);
3383                  activity.attach(appContext, this, getInstrumentation(), r.token,
3384                          r.ident, app, r.intent, r.activityInfo, title, r.parent,
3385                          r.embeddedID, r.lastNonConfigurationInstances, config,
3386                          r.referrer, r.voiceInteractor, window, r.configCallback,
3387                          r.assistToken);
3388  
3389                  if (customIntent != null) {
3390                      activity.mIntent = customIntent;
3391                  }
3392                  r.lastNonConfigurationInstances = null;
3393                  checkAndBlockForNetworkAccess();
3394                  activity.mStartedActivity = false;
3395                  int theme = r.activityInfo.getThemeResource();
3396                  if (theme != 0) {
3397                      activity.setTheme(theme);
3398                  }
3399  
3400                  activity.mCalled = false;
3401                  if (r.isPersistable()) {
3402                      mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
3403                  } else {
3404                      mInstrumentation.callActivityOnCreate(activity, r.state);
3405                  }
3406                  if (!activity.mCalled) {
3407                      throw new SuperNotCalledException(
3408                          "Activity " + r.intent.getComponent().toShortString() +
3409                          " did not call through to super.onCreate()");
3410                  }
3411                  r.activity = activity;
3412                  mLastReportedWindowingMode.put(activity.getActivityToken(),
3413                          config.windowConfiguration.getWindowingMode());
3414              }
3415              r.setState(ON_CREATE);
3416  
3417              // updatePendingActivityConfiguration() reads from mActivities to update
3418              // ActivityClientRecord which runs in a different thread. Protect modifications to
3419              // mActivities to avoid race.
3420              synchronized (mResourcesManager) {
3421                  mActivities.put(r.token, r);
3422              }
3423  
3424          } catch (SuperNotCalledException e) {
3425              throw e;
3426  
3427          } catch (Exception e) {
3428              if (!mInstrumentation.onException(activity, e)) {
3429                  throw new RuntimeException(
3430                      "Unable to start activity " + component
3431                      + ": " + e.toString(), e);
3432              }
3433          }
3434  
3435          return activity;
3436      }

在3331 行我们可以看到创建了上下文对象appContext ,并传入Activity的attach方法中,将Activity与上下文对象appContext 关联起来,这个上下文对象appContext 的具体类型是什么,我们接着查看createBaseContextForActivity方法,代码如下所示:

frameworks/base/core/java/android/app/ActivityThread.java

private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
3514          final int displayId;
3515          try {
3516              displayId = ActivityTaskManager.getService().getDisplayId(r.token);
3517          } catch (RemoteException e) {
3518              throw e.rethrowFromSystemServer();
3519          }
3520  
3521          ContextImpl appContext = ContextImpl.createActivityContext(
3522                  this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
3523  
3524          // The rotation adjustments must be applied before creating the activity, so the activity
3525          // can get the adjusted display info during creation.
3526          if (r.mPendingFixedRotationAdjustments != null) {
3527              // The adjustments should have been set by handleLaunchActivity, so the last one is the
3528              // override for activity resources.
3529              if (mActiveRotationAdjustments != null && !mActiveRotationAdjustments.isEmpty()) {
3530                  mResourcesManager.overrideTokenDisplayAdjustments(r.token,
3531                          mActiveRotationAdjustments.get(
3532                                  mActiveRotationAdjustments.size() - 1).second);
3533              }
3534              r.mPendingFixedRotationAdjustments = null;
3535          }
3536  
3537          final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
3538          // For debugging purposes, if the activity's package name contains the value of
3539          // the "debug.use-second-display" system property as a substring, then show
3540          // its content on a secondary display if there is one.
3541          String pkgName = SystemProperties.get("debug.second-display.pkg");
3542          if (pkgName != null && !pkgName.isEmpty()
3543                  && r.packageInfo.mPackageName.contains(pkgName)) {
3544              for (int id : dm.getDisplayIds()) {
3545                  if (id != Display.DEFAULT_DISPLAY) {
3546                      Display display =
3547                              dm.getCompatibleDisplay(id, appContext.getResources());
3548                      appContext = (ContextImpl) appContext.createDisplayContext(display);
3549                      break;
3550                  }
3551              }
3552          }
3553          return appContext;
3554      }

这里可以得出结论,上下文对象appContext 的具体类型就是ContextImpl 。Activity的attach方法中将ContextImpl赋值给ContextWrapper的成员变量mBase中,因此,mBase具体指向就是ContextImpl 。

那么,我们紧接着来查看ContextImpl的startService方法,代码如下所示:

@Override
@Override
1668      public ComponentName startService(Intent service) {
1669          warnIfCallingFromSystemProcess();
1670          return startServiceCommon(service, false, mUser);
1671      }
1672  

1695      private ComponentName startServiceCommon(Intent service, boolean requireForeground,
1696              UserHandle user) {
1697          try {
1698              validateServiceIntent(service);
1699              service.prepareToLeaveProcess(this);
1700              ComponentName cn = ActivityManager.getService().startService(
1701                      mMainThread.getApplicationThread(), service,
1702                      service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
1703                      getOpPackageName(), getAttributionTag(), user.getIdentifier());
1704              if (cn != null) {
1705                  if (cn.getPackageName().equals("!")) {
1706                      throw new SecurityException(
1707                              "Not allowed to start service " + service
1708                              + " without permission " + cn.getClassName());
1709                  } else if (cn.getPackageName().equals("!!")) {
1710                      throw new SecurityException(
1711                              "Unable to start service " + service
1712                              + ": " + cn.getClassName());
1713                  } else if (cn.getPackageName().equals("?")) {
1714                      throw new IllegalStateException(
1715                              "Not allowed to start service " + service + ": " + cn.getClassName());
1716                  }
1717              }
1718              return cn;
1719          } catch (RemoteException e) {
1720              throw e.rethrowFromSystemServer();
1721          }
1722      }

startService方法中会return startServiceCommon方法,在startServiceCommon方法中会在1700行处调用ActivityManager的getService方法,会返回一个IActivityManager 单例对象。对应的是ActivityManagerService继承IActivityManager.stub

 @UnsupportedAppUsage
4545      public static IActivityManager getService() {
4546          return IActivityManagerSingleton.get();
4547      }
4548  
4549      private static IActivityTaskManager getTaskService() {
4550          return ActivityTaskManager.getService();
4551      }
4552  
4553      @UnsupportedAppUsage
4554      private static final Singleton<IActivityManager> IActivityManagerSingleton =
4555              new Singleton<IActivityManager>() {
4556                  @Override
4557                  protected IActivityManager create() {
4558                      final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
4559                      final IActivityManager am = IActivityManager.Stub.asInterface(b);
4560                      return am;
4561                  }
4562              };
4563  

我们继续看startService的实现:

    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        enforceNotIsolatedCaller("startService");
        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        if (callingPackage == null) {
            throw new IllegalArgumentException("callingPackage cannot be null");
        }

        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
                "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
        synchronized(this) {
            // 获取进程号
            final int callingPid = Binder.getCallingPid();
            // 获取线程号
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                // 关键方法,调用startServiceLocked()
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

剩下的转入ActiveServices这个类的内部实现,不做赘述了。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-15 11:54:32  更:2021-10-15 11:56:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:52:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码