BluetoothManagerService存储蓝牙状态过程

/ android / 没有评论 / 692浏览

用到的代码文件

frameworks/base/services/core/java/:
com/android/server/BluetoothManagerService.java

frameworks/base/core/java/:
android/provider/Settings.java
android/app/backup/BackupManager.java

frameworks/base/packages/SettingsProvider/src/:
com/android/providers/settings/SettingsProvider.java
com/android/providers/settings/SettingsState.java

代码执行流程图

BluetoothManagerService 查看原图

模块编译

mm frameworks/base/services/
mm frameworks/base/packages/SettingsProvider/

BluetoothManagerService存储蓝牙状态过程

下面的代码是以android N(api 24)为基础。

本文基于高通(Qualcomm)平台基线。

SettingsProvider执行流程: android SettingsProvider onCreate执行流程

保存蓝牙的状态从这个方法开始。
进入BluetoothManagerService类的persistBluetoothSetting()方法中。

/**
 *  Save the Bluetooth on/off state
 *
 */
private void persistBluetoothSetting(int value) {
    //value: 0
    Settings.Global.putInt(mContext.getContentResolver(),
                           Settings.Global.BLUETOOTH_ON,
                           value);
}

下面进入Settings类的内部类Global的putInt()方法中。

public static boolean putInt(ContentResolver cr, 
        String name, int value) {
    //name: bluetooth_on value: 0
    return putString(cr, name, Integer.toString(value));
}

public static boolean putString(ContentResolver resolver,
        String name, String value) {
    return putStringForUser(resolver, name, 
            value, UserHandle.myUserId());
}

public static boolean putStringForUser(ContentResolver resolver,
        String name, String value, int userHandle) {
    // userHandle: 0
    // Global and Secure have the same access 
    // policy so we can forward writes
    if (MOVED_TO_SECURE.contains(name)) {// -> false
        Log.w(TAG, "Setting " + name 
                + " has moved from android.provider.Settings.Global"
                + " to android.provider.Settings.Secure, "
                + "value is unchanged.");
        return Secure.putStringForUser(resolver, 
                name, value, userHandle);
    }
    return sNameValueCache.putStringForUser(resolver, 
            name, value, userHandle);
}

下面进入Settings类的内部类NameValueCache的putStringForUser()方法中。

public boolean putStringForUser(ContentResolver cr, 
        String name, String value, final int userHandle) {
    try {
        Bundle arg = new Bundle();
        arg.putString(Settings.NameValueTable.VALUE, value);
        arg.putInt(CALL_METHOD_USER_KEY, userHandle);
        IContentProvider cp = lazyGetProvider(cr);
        //cr.getPackageName(): android
        Log.d("NameValueCache","cr.getPackageName(): "
                +cr.getPackageName());
        cp.call(cr.getPackageName(), 
                mCallSetCommand, name, arg);
    } catch (RemoteException e) {
        Log.w(TAG, "Can't set key " + name + " in " + mUri, e);
        return false;
    }
    return true;
}

下面进入NameValueCache类的lazyGetProvider()方法中。

private IContentProvider lazyGetProvider(ContentResolver cr) {
    //mUri: content://settings/global
    Log.d("NameValueCache","mUri: "+mUri);
    IContentProvider cp = null;
    synchronized (NameValueCache.this) {
        cp = mContentProvider;
        if (cp == null) {
            cp = mContentProvider = cr.acquireProvider(
                    mUri.getAuthority());
        }
        if (null!=cp){
            //cp: android.content.ContentProvider$Transport
            Log.d("NameValueCache","cp: "+cp.getClass().getName());
        }
    }
    return cp;
}

下面进入SettingsProvider类的call()方法中。

@Override
public Bundle call(String method, String name, Bundle args) {
    Log.d(LOG_TAG,"method: "+method);//PUT_global
    Log.d(LOG_TAG,"name: "+name);//bluetooth_on
    Log.d(LOG_TAG,"args: "+args);//args: Bundle[{_user=0, value=0}]
    final int requestingUserId = getRequestingUserId(args);
    Log.d(LOG_TAG,"requestingUserId: "+requestingUserId);//0
    switch (method) {
        case Settings.CALL_METHOD_GET_GLOBAL: {
            Setting setting = getGlobalSetting(name);
            return packageValueForCallResult(setting, i
                    sTrackingGeneration(args));
        }

        case Settings.CALL_METHOD_GET_SECURE: {
            Setting setting = getSecureSetting(name, requestingUserId);
            return packageValueForCallResult(setting, 
                          isTrackingGeneration(args));
        }

        case Settings.CALL_METHOD_GET_SYSTEM: {
            Setting setting = getSystemSetting(name, requestingUserId);
            return packageValueForCallResult(setting, 
                          isTrackingGeneration(args));
        }
        /*
          * 进入这里
          */
        case Settings.CALL_METHOD_PUT_GLOBAL: {
            String value = getSettingValue(args);
            Log.d(LOG_TAG,"value: "+value);//0
            insertGlobalSetting(name, value, requestingUserId, false);
            break;
        }

        case Settings.CALL_METHOD_PUT_SECURE: {
            String value = getSettingValue(args);
            insertSecureSetting(name, value, requestingUserId, false);
            break;
        }

        case Settings.CALL_METHOD_PUT_SYSTEM: {
            String value = getSettingValue(args);
            insertSystemSetting(name, value, requestingUserId);
            break;
        }

        default: {
            Slog.w(LOG_TAG, "call() with invalid method: " + method);
        } break;
    }

    return null;
}

下面进入SettingsProvider类的insertGlobalSetting()方法中。

private boolean insertGlobalSetting(String name, String value, 
        int requestingUserId, boolean forceNotify) {
    //forceNotify: false
    return mutateGlobalSetting(name, value, 
            requestingUserId, MUTATION_OPERATION_INSERT,
            forceNotify);
}

下面进入SettingsProvider类的mutateGlobalSetting()方法中。

private boolean mutateGlobalSetting(String name, String value, 
        int requestingUserId, int operation, boolean forceNotify) {
    Log.d(LOG_TAG,"name: "+name);//name: bluetooth_on
    Log.d(LOG_TAG,"value: "+value);// value: 0
    //requestingUserId: 0
    Log.d(LOG_TAG,"requestingUserId: "+requestingUserId);
    Log.d(LOG_TAG,"operation: "+operation);//operation: 1
    //forceNotify: false
    Log.d(LOG_TAG,"forceNotify: "+forceNotify);
    // Make sure the caller can change the settings - treated as secure.
    enforceWritePermission(
            Manifest.permission.WRITE_SECURE_SETTINGS);

    // Resolve the userId on whose behalf the call is made.
    final int callingUserId = 
            resolveCallingUserIdEnforcingPermissionsLocked(
                    requestingUserId);
    Log.d(LOG_TAG,"callingUserId: "+callingUserId);//callingUserId: 0
    // If this is a setting that is currently restricted for this user, 
    // do not allow unrestricting changes.
    if (isGlobalOrSecureSettingRestrictedForUser(name, 
            callingUserId, value,
            Binder.getCallingUid())) {
        return false;
    }

    // Perform the mutation.
    synchronized (mLock) {
        switch (operation) {
            /*
              * 进入这里
              */
            case MUTATION_OPERATION_INSERT: {
                return mSettingsRegistry
                        .insertSettingLocked(SETTINGS_TYPE_GLOBAL, 
                                UserHandle.USER_SYSTEM,
                                name, value, getCallingPackage(), 
                                forceNotify);
            }

            case MUTATION_OPERATION_DELETE: {
                return mSettingsRegistry.deleteSettingLocked(
                        SETTINGS_TYPE_GLOBAL,
                        UserHandle.USER_SYSTEM, name, 
                        forceNotify);
            }

            case MUTATION_OPERATION_UPDATE: {
                return mSettingsRegistry
                        .updateSettingLocked(SETTINGS_TYPE_GLOBAL, 
                                UserHandle.USER_SYSTEM,
                                name, value, getCallingPackage(), 
                                forceNotify);
            }
        }
    }

    return false;
}

下面进入SettingsProvider类的内部类SettingsRegistry的insertSettingLocked()方法中。

public boolean insertSettingLocked(int type, int userId, 
      String name, String value, String packageName, 
      boolean forceNotify) {
    final int key = makeKey(type, userId);
    Log.d("SettingsRegistry","key: "+key);//key: 0

    SettingsState settingsState = peekSettingsStateLocked(key);
    /*
      * 进入这里
      */
    final boolean success = settingsState
            .insertSettingLocked(name, value, packageName);
    Log.d("SettingsRegistry","success: "+success);//true
    Log.d("SettingsRegistry","forceNotify: "+forceNotify);//false

    if (forceNotify || success) {
        notifyForSettingsChange(key, name);
    }
    return success;
}

下面进入SettingsState类的insertSettingLocked()方法中。

// The settings provider must hold its lock when calling here.
public boolean insertSettingLocked(String name, 
        String value, String packageName) {
    //name: bluetooth_on value: 0 packageName: android
    if (TextUtils.isEmpty(name)) {
        return false;
    }

    Setting oldState = mSettings.get(name);
    String oldValue = (oldState != null) ? oldState.value : null;

    if (oldState != null) {// -> true
        Log.d("SettingsState","oldState!=null");
        if (!oldState.update(value, packageName)) {
            return false;
        }
    } else {
        Setting state = new Setting(name, value, packageName);
        mSettings.put(name, state);
    }
    //这个方法内部条件判断return了,没有执行
    updateMemoryUsagePerPackageLocked(packageName, 
            oldValue, value);
    /**
      * 进入这里
      */
    scheduleWriteIfNeededLocked();

    return true;
}

方法定义在SettingsState类中。

private void scheduleWriteIfNeededLocked() {
    Log.d(LOG_TAG,"mDirty: "+mDirty);//false
    // If dirty then we have a write already scheduled.
    if (!mDirty) {// -> true
        mDirty = true;
        writeStateAsyncLocked();
    }
}

方法定义在SettingsState类中。

private void writeStateAsyncLocked() {
    final long currentTimeMillis = SystemClock.uptimeMillis();

    // false
    Log.d(LOG_TAG,"mWriteScheduled: "+mWriteScheduled);
    if (mWriteScheduled) {
        mHandler.removeMessages(
                  MyHandler.MSG_PERSIST_SETTINGS);

        // If enough time passed, write without holding off anymore.
        final long timeSinceLastNotWrittenMutationMillis = 
                currentTimeMillis - mLastNotWrittenMutationTimeMillis;
        if (timeSinceLastNotWrittenMutationMillis 
                >= MAX_WRITE_SETTINGS_DELAY_MILLIS) {
            mHandler.obtainMessage(MyHandler
                    .MSG_PERSIST_SETTINGS).sendToTarget();
            return;
        }

        // Hold off a bit more as settings are frequently changing.
        final long maxDelayMillis =
                Math.max(mLastNotWrittenMutationTimeMillis
                + MAX_WRITE_SETTINGS_DELAY_MILLIS 
                - currentTimeMillis, 0);
        final long writeDelayMillis = 
                Math.min(WRITE_SETTINGS_DELAY_MILLIS, 
                        maxDelayMillis);

        Message message = mHandler
                .obtainMessage(MyHandler.MSG_PERSIST_SETTINGS);
        mHandler.sendMessageDelayed(message, writeDelayMillis);
    } else {// -> 进入这里
        mLastNotWrittenMutationTimeMillis = currentTimeMillis;
        /*
          * 构建了一个延时200ms的消息
          */
        Message message = mHandler
                .obtainMessage(MyHandler.MSG_PERSIST_SETTINGS);
        mHandler.sendMessageDelayed(message, 
                WRITE_SETTINGS_DELAY_MILLIS);
        mWriteScheduled = true;
    }
}

现在回到SettingsRegistry类的insertSettingLocked()方法中。

    ....
    //进入这里
    if (forceNotify || success) {
        notifyForSettingsChange(key, name);
    }
    ....

方法定义在SettingsRegistry类中。

private void notifyForSettingsChange(int key, String name) {
    // key: 0 name: bluetooth_on
    final int userId = getUserIdFromKey(key);
    Uri uri = getNotificationUriFor(key, name);
    Log.d("SettingsRegistry","userId: "+userId);// 0
    //content://settings/global/bluetooth_on
    Log.d("SettingsRegistry","uri: "+uri);

    mGenerationRegistry.incrementGeneration(key);

    mHandler.obtainMessage(
            MyHandler.MSG_NOTIFY_URI_CHANGED,
            userId, 0, uri).sendToTarget();

    if (isSecureSettingsKey(key)) { // -> false
        Log.d("SettingsRegistry","isSecureSettingsKey(key) is true");
        maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
                sSecureCloneToManagedSettings);
    } else if (isSystemSettingsKey(key)) {// -> false
        Log.d("SettingsRegistry","isSystemSettingsKey(key) is true");
        maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
                sSystemCloneToManagedSettings);
    }
    //执行这里
    mHandler.obtainMessage(
            MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
}

MyHandler是定义在SettingsRegistry类中的内部类。

private final class MyHandler extends Handler {
    private static final int MSG_NOTIFY_URI_CHANGED = 1;
    private static final int MSG_NOTIFY_DATA_CHANGED = 2;

    public MyHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_NOTIFY_URI_CHANGED: {
                final int userId = msg.arg1;
                Uri uri = (Uri) msg.obj;
                getContext().getContentResolver()
                        .notifyChange(uri, null, true, userId);
                if (DEBUG) {
                    Slog.v(LOG_TAG, "Notifying for " + userId + ": " + uri);
                }
            } break;
            //收到上面方法中的消息
            case MSG_NOTIFY_DATA_CHANGED: {
                mBackupManager.dataChanged();
            } break;
        }
    }
}

下面进入BackupManager类的dataChanged()方法中。
这个方法暂不深入研究了....

public void dataChanged() {
    checkServiceBinder();
    if (sService != null) {
        try {
            sService.dataChanged(mContext.getPackageName());
        } catch (RemoteException e) {
            Log.d(TAG, "dataChanged() couldn't connect");
        }
    }
}

上面流程中有个200ms后发送的消息,现在进入这个消息。
这个消息进入MyHandler中进行处理。
这个MyHandler是定义在SettingsState中的内部类。
跟上面SettingsRegistry类中的MyHandler类不是同一个。

private final class MyHandler extends Handler {
    public static final int MSG_PERSIST_SETTINGS = 1;

    public MyHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message message) {
        switch (message.what) {
            case MSG_PERSIST_SETTINGS: {
                Log.d("MyHandler","case MSG_PERSIST_SETTINGS");
                Runnable callback = (Runnable) message.obj;
                //进入这里
                doWriteState();
                //刚才消息没有附件obj
                if (callback != null) {
                    callback.run();
                }else{// ->进入这里
                    Log.d("MyHandler","callback is null");
                }
            }
            break;
        }
    }
}

下面进入SettingsState类的doWriteState()方法中。
通过这个方法可以看见将settings_global.xml文件重新生成了一份。
所以也就将我们蓝牙字段"bluetooth_on"对应的值也就更新了。

private void doWriteState() {
    Log.d(LOG_TAG,"method called doWriteState() start");
    if (DEBUG_PERSISTENCE) {
        Slog.i(LOG_TAG, "[PERSIST START]");
    }
    if (null!=mStatePersistFile){
        Log.d(LOG_TAG,"mStatePersistFile : "
              +mStatePersistFile.getAbsolutePath());
    }
    AtomicFile destination = new AtomicFile(mStatePersistFile);

    final int version;
    final ArrayMap<String, Setting> settings;

    synchronized (mLock) {
        version = mVersion;
        settings = new ArrayMap<>(mSettings);
        mDirty = false;
        mWriteScheduled = false;
    }

    FileOutputStream out = null;
    try {
        out = destination.startWrite();

        XmlSerializer serializer = Xml.newSerializer();
        serializer.setOutput(out, StandardCharsets.UTF_8.name());
        serializer.setFeature(
                "http://xmlpull.org/v1/doc/features.html#indent-output", 
                 true);
        serializer.startDocument(null, true);
        serializer.startTag(null, TAG_SETTINGS);
        serializer.attribute(null, ATTR_VERSION, 
                                      String.valueOf(version));

        final int settingCount = settings.size();
        Log.d(LOG_TAG,"settingCount: "+settingCount);
        for (int i = 0; i < settingCount; i++) {
            Setting setting = settings.valueAt(i);

            writeSingleSetting(mVersion, serializer, 
                    setting.getId(), setting.getName(),
                    setting.getValue(), setting.getPackageName());

            if (DEBUG_PERSISTENCE) {
                Slog.i(LOG_TAG, "[PERSISTED]" 
                        + setting.getName() + "=" + setting.getValue());
            }
        }

        serializer.endTag(null, TAG_SETTINGS);
        serializer.endDocument();
        destination.finishWrite(out);

        if (DEBUG_PERSISTENCE) {
            Slog.i(LOG_TAG, "[PERSIST END]");
        }
    } catch (Throwable t) {
        Slog.wtf(LOG_TAG, 
                "Failed to write settings, restoring backup", t);
        destination.failWrite(out);
    } finally {
        IoUtils.closeQuietly(out);
    }
    Log.d(LOG_TAG,"method called doWriteState() end");
}