PowerManagerService服务

一、功能介绍

PMS作用:

1)向上提供给应用程序接口,例如音频场景中保持系统唤醒、消息通知中唤醒手机屏幕场景;

2)向下决策HAL层以及Kernel层来控制设备待机状态,控制显示屏、背光灯、距离传感器、光线传感器等硬件设备的状态;

二、电源管理架构

三、UML

1)PMS服务继承SystemService类,说明是系统服务;实现了Watchdog.Monitor接口,重写其方法,将PMS服务纳入Watchdog监听

2)Constants、DisplayGroupPowerChangeListener、DreamManagerStateListener、PowerGroupWakefulnessChangeListener、static Injector、static NativeWrapper、static final ProfilePowerState、ForegroundProfileObserver、DeviceStateListener、LocalService、BinderService、SuspendBlockImpl、WakeLock、PowerManagerHandlerCallback、SettingsObserver、DockReceiver、BatteryReceiver 、UserSwitchedReceiver为PMS服务的内部类,Clock为内部接口

类名

作用

Constants

设置系统Settings global power相关的属性值

DisplayGroupPowerChangeListener

监听显示组(屏幕、显示器)电源状态发生变化

DreamManagerStateListener

监听屏保状态的变化

PowerGroupWakefulnessChangeListener

监听电源组(display、audio、sendor group等)休眠唤醒状态状态监听

static NativeWrapper

NativeWrapper对象封装相关native接口

static final ProfilePowerState

记录用户的状态信息

ForegroundProfileObserver

监听用户切换和前台配置文件切换事件

DeviceStateListener

监听设备状态变化

LocalService

提供进程内其它模块的API

BinderService

提供Binder Call API

SuspendBlockImpl

对wakelock管理实现,调用native方法

WakeLock

Wakelock类

PowerManagerHandlerCallback

power相关的一些callback回调实现

SettingsObserver

监听系统设置发生变化状态

DockReceiver

监听设备电源底座连接或断开状态,并当地更新电源状态

BatteryReceiver

监听电池状态发生变化广播

UserSwitchedReceiver

监听用户切换广播

Clock

封装获取uptimeMillis和elapsedRealtime的接口

四、PMS模块解析

根据PMS对外提供的功能、内部的模块划分,解析各功能或模块的代码实现。

 4.1 PMS启动初始化

public PowerManagerService(Context context) {
    this(context, new Injector());
}

@VisibleForTesting
PowerManagerService(Context context, Injector injector) {
    super(context);

    mContext = context;
    mBinderService = new BinderService(mContext);    // 用于注册服务
    mLocalService = new LocalService();    // 获取LocalService对象,注册服务到本地
    mNativeWrapper = injector.createNativeWrapper();    // 调用native方法的对象
    mSystemProperties = injector.createSystemPropertiesWrapper();    // systemproperity封装
    mClock = injector.createClock();    // systemclock封装
    mInjector = injector;

    mHandlerThread = new ServiceThread(TAG,
            Process.THREAD_PRIORITY_DISPLAY, /* allowIo= */ false);    // THREAD_PRIORITY_DISPLAY是最高的优先级之一
    mHandlerThread.start();
    mHandler = injector.createHandler(mHandlerThread.getLooper(),    // 创建handler,实现消息异步处理
            new PowerManagerHandlerCallback());
    mConstants = new Constants(mHandler);    // 监听系统设置的变化,并根据设置项的值来更新Constants中的常量,以便在电源管理服务中使用这些常量来控制相关的行为
    mAmbientDisplayConfiguration = mInjector.createAmbientDisplayConfiguration(context);    // 获取环境显示的配置信息
    mAmbientDisplaySuppressionController =
            mInjector.createAmbientDisplaySuppressionController(
                    mAmbientSuppressionChangedCallback);    // 环境显示是指设备或屏幕在休眠或关闭状态下,以一种低功耗的方式显示有限的信息
    mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock);    // 检测用户当前是否注意手机并通知PowerManagerService更新用户活动
    mFaceDownDetector = new FaceDownDetector(this::onFlip);    // 检测手机是否放置于屏幕向下
    mScreenUndimDetector = new ScreenUndimDetector();    // 检测用户手动取消屏幕变暗并且获取唤醒锁以暂时保持屏幕常亮

    mBatterySavingStats = new BatterySavingStats(mLock);    // 用于跟踪电池耗电速率,监测电池的电量变化和时间来计算电池的耗电速率
    mBatterySaverPolicy =
            mInjector.createBatterySaverPolicy(mLock, mContext, mBatterySavingStats);    // 用于决定是否启用省电模式
    mBatterySaverController = mInjector.createBatterySaverController(mLock, mContext,
            mBatterySaverPolicy, mBatterySavingStats);    // 负责省电模式转换逻辑
    mBatterySaverStateMachine = mInjector.createBatterySaverStateMachine(mLock, mContext,
            mBatterySaverController);    // 用于决定何时启用/禁用省电模式

    mLowPowerStandbyController = mInjector.createLowPowerStandbyController(mContext,
            Looper.getMainLooper());    // 控制低功耗待机状态
    mInattentiveSleepWarningOverlayController =
            mInjector.createInattentiveSleepWarningController();    // 与系统UI通信,用于显示/隐藏非用户活动警告覆盖层(如低电量提示)
    mPermissionCheckerWrapper = mInjector.createPermissionCheckerWrapper();    // 用于检测app的执行权限
    mPowerPropertiesWrapper = mInjector.createPowerPropertiesWrapper();    // power属性
    mDeviceConfigProvider = mInjector.createDeviceConfigParameterProvider();    // 访问和处理与 display相关的设备配置参数

    mPowerGroupWakefulnessChangeListener = new PowerGroupWakefulnessChangeListener();    // 监听唤醒状态的变化,并根据需要更新相关的状态和执行相应的操作

    // Save brightness values:
    // Get float values from config.
    // Store float if valid
    // Otherwise, get int values and convert to float and then store.
    final float min = mContext.getResources().getFloat(com.android.internal.R.dimen
            .config_screenBrightnessSettingMinimumFloat);    // 从资源文件中获取的屏幕亮度设置的最小值
    final float max = mContext.getResources().getFloat(com.android.internal.R.dimen
            .config_screenBrightnessSettingMaximumFloat);    // 从资源文件中获取的屏幕亮度设置的最大值
    final float def = mContext.getResources().getFloat(com.android.internal.R.dimen
            .config_screenBrightnessSettingDefaultFloat);    // 从资源文件中获取的屏幕亮度默认值
    final float doze = mContext.getResources().getFloat(com.android.internal.R.dimen
            .config_screenBrightnessDozeFloat);
    final float dim = mContext.getResources().getFloat(com.android.internal.R.dimen
            .config_screenBrightnessDimFloat);

    if (min == INVALID_BRIGHTNESS_IN_CONFIG || max == INVALID_BRIGHTNESS_IN_CONFIG
            || def == INVALID_BRIGHTNESS_IN_CONFIG) {
        mScreenBrightnessMinimum = BrightnessSynchronizer.brightnessIntToFloat(
                mContext.getResources().getInteger(com.android.internal.R.integer
                        .config_screenBrightnessSettingMinimum));
        mScreenBrightnessMaximum = BrightnessSynchronizer.brightnessIntToFloat(
                mContext.getResources().getInteger(com.android.internal.R.integer
                        .config_screenBrightnessSettingMaximum));
        mScreenBrightnessDefault = BrightnessSynchronizer.brightnessIntToFloat(
                mContext.getResources().getInteger(com.android.internal.R.integer
                        .config_screenBrightnessSettingDefault));
    } else {
        mScreenBrightnessMinimum = min;
        mScreenBrightnessMaximum = max;
        mScreenBrightnessDefault = def;
    }
    if (doze == INVALID_BRIGHTNESS_IN_CONFIG) {
        mScreenBrightnessDoze = BrightnessSynchronizer.brightnessIntToFloat(
                mContext.getResources().getInteger(com.android.internal.R.integer
                        .config_screenBrightnessDoze));
    } else {
        mScreenBrightnessDoze = doze;
    }
    if (dim == INVALID_BRIGHTNESS_IN_CONFIG) {
        mScreenBrightnessDim = BrightnessSynchronizer.brightnessIntToFloat(
                mContext.getResources().getInteger(com.android.internal.R.integer
                        .config_screenBrightnessDim));
    } else {
        mScreenBrightnessDim = dim;
    }

    synchronized (mLock) {
        // 系统启动阶段,获取保持cpu唤醒状态的wakelock
        mBootingSuspendBlocker =
                mInjector.createSuspendBlocker(this, "PowerManagerService.Booting");
        // 在特定情况下,如app需要保持cpu运行,获取保持cpu唤醒状态的wakelock
        mWakeLockSuspendBlocker =
                mInjector.createSuspendBlocker(this, "PowerManagerService.WakeLocks");
        // 保持亮屏,获取保持cpu唤醒状态的wakelock
        mDisplaySuspendBlocker =
                mInjector.createSuspendBlocker(this, "PowerManagerService.Display");
        if (mBootingSuspendBlocker != null) {
            mBootingSuspendBlocker.acquire();
            mHoldingBootingSuspendBlocker = true;
        }
        if (mDisplaySuspendBlocker != null) {
            mDisplaySuspendBlocker.acquire(HOLDING_DISPLAY_SUSPEND_BLOCKER);
            mHoldingDisplaySuspendBlocker = true;
        }
        mHalAutoSuspendModeEnabled = false;
        mHalInteractiveModeEnabled = true;

        mWakefulnessRaw = WAKEFULNESS_AWAKE;
        sQuiescent = mSystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1")
                || InitProperties.userspace_reboot_in_progress().orElse(false);

        mNativeWrapper.nativeInit(this);
        mNativeWrapper.nativeSetAutoSuspend(false);
        mNativeWrapper.nativeSetPowerMode(Mode.INTERACTIVE, true);
        mNativeWrapper.nativeSetPowerMode(Mode.DOUBLE_TAP_TO_WAKE, false);
        mInjector.invalidateIsInteractiveCaches();
    }
}

 @Override
public void onStart() {
    // 注册服务到Service Manager
    publishBinderService(Context.POWER_SERVICE, mBinderService, /* allowIsolated= */ false,
            DUMP_FLAG_PRIORITY_DEFAULT | DUMP_FLAG_PRIORITY_CRITICAL);
    // 注册服务到logcal service,便于system_server进程内部其他模块获取
    publishLocalService(PowerManagerInternal.class, mLocalService);
    // 加入watchdog监听
    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
}

 @Override
public void onBootPhase(int phase) {
    if (phase == PHASE_SYSTEM_SERVICES_READY) {
        systemReady();

    } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
        incrementBootCount();

    } else if (phase == PHASE_BOOT_COMPLETED) {
        synchronized (mLock) {
            final long now = mClock.uptimeMillis();
            mBootCompleted = true;
            mDirty |= DIRTY_BOOT_COMPLETED;

            mBatterySaverStateMachine.onBootCompleted();
            userActivityNoUpdateLocked(
                    now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);

            updatePowerStateLocked();
            if (sQuiescent) {
                sleepPowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP),
                        mClock.uptimeMillis(),
                        PowerManager.GO_TO_SLEEP_REASON_QUIESCENT,
                        Process.SYSTEM_UID);
            }

            mContext.getSystemService(DeviceStateManager.class).registerCallback(
                    new HandlerExecutor(mHandler), new DeviceStateListener());
        }
    }
}

private void systemReady() {
        synchronized (mLock) {
            mSystemReady = true;
            mDreamManager = getLocalService(DreamManagerInternal.class);
            mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
            mPolicy = getLocalService(WindowManagerPolicy.class);
            mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
            mAttentionDetector.systemReady(mContext);
            // 用于无线充电检测
            SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());

            // The notifier runs on the system server's main looper so as not to interfere
            // with the animations and other critical functions of the power manager.
            mBatteryStats = BatteryStatsService.getService();
            mNotifier = mInjector.createNotifier(Looper.getMainLooper(), mContext, mBatteryStats,
                    mInjector.createSuspendBlocker(this, "PowerManagerService.Broadcasts"),
                    mPolicy, mFaceDownDetector, mScreenUndimDetector,
                    BackgroundThread.getExecutor());

            mPowerGroups.append(Display.DEFAULT_DISPLAY_GROUP,
                    new PowerGroup(WAKEFULNESS_AWAKE, mPowerGroupWakefulnessChangeListener,
                            mNotifier, mDisplayManagerInternal, mClock.uptimeMillis()));
            DisplayGroupPowerChangeListener displayGroupPowerChangeListener =
                    new DisplayGroupPowerChangeListener();
            mDisplayManagerInternal.registerDisplayGroupListener(displayGroupPowerChangeListener);

            // This DreamManager method does not acquire a lock, so it should be safe to call.
            mDreamManager.registerDreamManagerStateListener(new DreamManagerStateListener());

            mWirelessChargerDetector = mInjector.createWirelessChargerDetector(sensorManager,
                    mInjector.createSuspendBlocker(
                            this, "PowerManagerService.WirelessChargerDetector"),
                    mHandler);
            mSettingsObserver = new SettingsObserver(mHandler);

            mLightsManager = getLocalService(LightsManager.class);
            mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
            updateDeviceConfigLocked();
            mDeviceConfigProvider.addOnPropertiesChangedListener(BackgroundThread.getExecutor(),
                    properties -> {
                        synchronized (mLock) {
                            updateDeviceConfigLocked();
                            updateWakeLockDisabledStatesLocked();
                        }
                    });

            // Initialize display power management.
            mDisplayManagerInternal.initPowerManagement(
                    mDisplayPowerCallbacks, mHandler, sensorManager);

            // Create power groups for display groups other than DEFAULT_DISPLAY_GROUP.
            addPowerGroupsForNonDefaultDisplayGroupLocked();

            try {
                final ForegroundProfileObserver observer = new ForegroundProfileObserver();
                ActivityManager.getService().registerUserSwitchObserver(observer, TAG);
            } catch (RemoteException e) {
                // Shouldn't happen since in-process.
            }

            mLowPowerStandbyController.systemReady();

            // Go.
            readConfigurationLocked();
            updateSettingsLocked();
            mDirty |= DIRTY_BATTERY_STATE;    // 电源状态发生变化
            updatePowerStateLocked();    // 更新电源状态
        }

    final ContentResolver resolver = mContext.getContentResolver();
    mConstants.start(resolver);

    mBatterySaverController.systemReady();
    mBatterySaverPolicy.systemReady();
    mFaceDownDetector.systemReady(mContext);
    mScreenUndimDetector.systemReady(mContext);

    // Register for settings changes.
    // 注册settings变化的监听,当发生变化时会回调Constants的onChange方法
    resolver.registerContentObserver(Settings.Secure.getUriFor(
            Settings.Secure.SCREENSAVER_ENABLED),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.Secure.getUriFor(
            Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.Secure.getUriFor(
            Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.System.getUriFor(
            Settings.System.SCREEN_OFF_TIMEOUT),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.Secure.getUriFor(
            Settings.Secure.SLEEP_TIMEOUT),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.Secure.getUriFor(
            Settings.Secure.ATTENTIVE_TIMEOUT),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.Global.getUriFor(
            Settings.Global.STAY_ON_WHILE_PLUGGED_IN),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.System.getUriFor(
            Settings.System.SCREEN_BRIGHTNESS_MODE),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.System.getUriFor(
            Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.Global.getUriFor(
            Settings.Global.THEATER_MODE_ON),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.Secure.getUriFor(
            Settings.Secure.DOZE_ALWAYS_ON),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.Secure.getUriFor(
            Settings.Secure.DOUBLE_TAP_TO_WAKE),
            false, mSettingsObserver, UserHandle.USER_ALL);
    resolver.registerContentObserver(Settings.Global.getUriFor(
            Settings.Global.DEVICE_DEMO_MODE),
            false, mSettingsObserver, UserHandle.USER_SYSTEM);

    // Register for broadcasts from other components of the system.
    // 注册电源变化的广播,接收电源变化的信息,并做相应的处理
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_BATTERY_CHANGED);
    filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
    mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);

    // 屏保发生变化的广播
    filter = new IntentFilter();
    filter.addAction(Intent.ACTION_DREAMING_STARTED);
    filter.addAction(Intent.ACTION_DREAMING_STOPPED);
    mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);
    
    // 系统设置发生变化的广播
    filter = new IntentFilter();
    filter.addAction(Intent.ACTION_USER_SWITCHED);
    mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);

    // 设备的对接状态发生变化时(例如连接或断开手机底座等),系统会发送此广播消息
    filter = new IntentFilter();
    filter.addAction(Intent.ACTION_DOCK_EVENT);
    mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);
}

systemReady完成的工作主要如下:

1)获取与PowerManangerService相关的系统服务以及本地服务

2)获取屏幕最大、最小以及默认亮度值

3)创建SensorManager对象用于与WirelessChargerDetector交互

4)创建Notifier对象,用户通知系统电源状态的改变

5)调用DisplayManagerInternal的initPowerMannagerMent()方法来初始化Power显示模块

6)注册SettingsObserver监听系统设置的变化

7)注册一些广播接收器,如电池状态变化、Settings变化等

4.2 wakelock管理

Android Wakelock管理【app至kernel】-CSDN博客

4.3 亮灭屏管理

基本流程:

这里只列举了亮灭屏管理中PMS的代码。

1)灭屏休眠

@Override // Binder call
@RequiresPermission(android.Manifest.permission.DEVICE_POWER)
public void goToSleep(long eventTime, int reason, int flags) {
    goToSleepInternal(DEFAULT_DISPLAY_GROUP_IDS, eventTime, reason, flags);
}

@RequiresPermission(android.Manifest.permission.DEVICE_POWER)
private void goToSleepInternal(IntArray groupIds, long eventTime, int reason, int flags) {
    final long now = mClock.uptimeMillis();
    if (eventTime > now) {
        Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
        throw new IllegalArgumentException("event time must not be in the future");
    }

    mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
            /* message= */ null);

    boolean isNoDoze = (flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0;
    int uid = Binder.getCallingUid();
    final long ident = Binder.clearCallingIdentity();
    try {
        synchronized (mLock) {
            for (int i = 0; i < groupIds.size(); i++) {
                int groupId = groupIds.get(i);
                PowerGroup powerGroup = mPowerGroups.get(groupId);
                if (powerGroup == null) {
                    throw new IllegalArgumentException("power group(" + groupId
                            + ") doesn't exist");
                }
                if ((flags & PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP) != 0) {
                    if (powerGroup.hasWakeLockKeepingScreenOnLocked()) {
                        continue;
                    }
                }
                if (isNoDoze) {
                    sleepPowerGroupLocked(powerGroup, eventTime, reason, uid);
                } else {
                    dozePowerGroupLocked(powerGroup, eventTime, reason, uid);
                }
            }
        }
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}

@GuardedBy("mLock")
private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime,
        @GoToSleepReason int reason, int uid) {
    if (DEBUG_SPEW) {
        Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime
                + ", groupId=" + powerGroup.getGroupId()
                + ", reason=" + PowerManager.sleepReasonToString(reason) + ", uid=" + uid);
    }
    if (!mBootCompleted || !mSystemReady) {
        return false;
    }

    return powerGroup.sleepLocked(eventTime, uid, reason);
}
// PowerGroup.java
boolean sleepLocked(long eventTime, int uid, @PowerManager.GoToSleepReason int reason) {
    if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
        return false;
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "sleepPowerGroup");
    try {
        Slog.i(TAG,
                "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ", reason="
                        + PowerManager.sleepReasonToString(reason) + ")...");
        setSandmanSummonedLocked(/* isSandmanSummoned= */ true);
        setWakefulnessLocked(WAKEFULNESS_ASLEEP, eventTime, uid, reason, /* opUid= */0,
                /* opPackageName= */ null, /* details= */ null);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return true;
}

/**
 * Sets the {@code wakefulness} value for this {@link PowerGroup}.
 *
 * @return {@code true} if the wakefulness value was changed; {@code false} otherwise.
 */
boolean setWakefulnessLocked(int newWakefulness, long eventTime, int uid, int reason, int opUid,
        String opPackageName, String details) {
    if (mWakefulness != newWakefulness) {
        if (newWakefulness == WAKEFULNESS_AWAKE) {
            setLastPowerOnTimeLocked(eventTime);
            setIsPoweringOnLocked(true);
            mLastWakeTime = eventTime;
        } else if (isInteractive(mWakefulness) && !isInteractive(newWakefulness)) {
            mLastSleepTime = eventTime;
        }
        mWakefulness = newWakefulness;
        mWakefulnessListener.onWakefulnessChangedLocked(mGroupId, mWakefulness, eventTime,
                reason, uid, opUid, opPackageName, details);
        return true;
    }
    return false;
}
// PowerManagerService.java
private final class PowerGroupWakefulnessChangeListener implements
        PowerGroup.PowerGroupListener {
    @GuardedBy("mLock")
    @Override
    public void onWakefulnessChangedLocked(int groupId, int wakefulness, long eventTime,
            int reason, int uid, int opUid, String opPackageName, String details) {
        mWakefulnessChanging = true;
        mDirty |= DIRTY_WAKEFULNESS;
        if (wakefulness == WAKEFULNESS_AWAKE) {
            // Kick user activity to prevent newly awake group from timing out instantly.
            // The dream may end without user activity if the dream app crashes / is updated,
            // don't poke the user activity timer for these wakes.
            int flags = reason == PowerManager.WAKE_REASON_DREAM_FINISHED
                    ? PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0;
            userActivityNoUpdateLocked(mPowerGroups.get(groupId), eventTime,
                    PowerManager.USER_ACTIVITY_EVENT_OTHER, flags, uid);
        }
        mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS;
        mNotifier.onGroupWakefulnessChangeStarted(groupId, wakefulness, reason, eventTime);
        updateGlobalWakefulnessLocked(eventTime, reason, uid, opUid, opPackageName, details);
        updatePowerStateLocked();
    }
}
// Notifier.java
public void onGroupWakefulnessChangeStarted(int groupId, int wakefulness, int changeReason,
        long eventTime) {
    final boolean isInteractive = PowerManagerInternal.isInteractive(wakefulness);

    boolean isNewGroup = false;
    Interactivity interactivity = mInteractivityByGroupId.get(groupId);
    if (interactivity == null) {
        isNewGroup = true;
        interactivity = new Interactivity();
        mInteractivityByGroupId.put(groupId, interactivity);
    }
    if (isNewGroup || interactivity.isInteractive != isInteractive) {
        // Finish up late behaviors if needed.
        if (interactivity.isChanging) {
            handleLateInteractiveChange(groupId);
        }

        // Handle early behaviors.
        interactivity.isInteractive = isInteractive;
        interactivity.changeReason = changeReason;
        interactivity.changeStartTime = eventTime;
        interactivity.isChanging = true;
        handleEarlyInteractiveChange(groupId);
    }
}

private void handleEarlyInteractiveChange(int groupId) {
    synchronized (mLock) {
        Interactivity interactivity = mInteractivityByGroupId.get(groupId);
        if (interactivity == null) {
            Slog.e(TAG, "no Interactivity entry for groupId:" + groupId);
            return;
        }
        final int changeReason = interactivity.changeReason;
        if (interactivity.isInteractive) {
            // 最终通知PowerManagerService模块处理
            mHandler.post(() -> mPolicy.startedWakingUp(groupId, changeReason));
        } else {
            mHandler.post(() -> mPolicy.startedGoingToSleep(groupId, changeReason));
        }
    }
}

 2)亮屏

@Override // Binder call
public void wakeUp(long eventTime, @WakeReason int reason, String details,
        String opPackageName) {
    final long now = mClock.uptimeMillis();
    if (eventTime > now) {
        Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
        throw new IllegalArgumentException("event time must not be in the future");
    }

    mContext.enforceCallingOrSelfPermission(
            android.Manifest.permission.DEVICE_POWER, null);

    final int uid = Binder.getCallingUid();
    final long ident = Binder.clearCallingIdentity();
    try {
        synchronized (mLock) {
            if (!mBootCompleted && sQuiescent) {
                mDirty |= DIRTY_QUIESCENT;
                updatePowerStateLocked();
                return;
            }
            wakePowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), eventTime,
                    reason, details, uid, opPackageName, uid);
        }
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}

@GuardedBy("mLock")
private void wakePowerGroupLocked(final PowerGroup powerGroup, long eventTime,
        @WakeReason int reason, String details, int uid, String opPackageName, int opUid) {
    if (DEBUG_SPEW) {
        Slog.d(TAG, "wakePowerGroupLocked: eventTime=" + eventTime
                + ", groupId=" + powerGroup.getGroupId()
                + ", reason=" + PowerManager.wakeReasonToString(reason) + ", uid=" + uid);
    }
    if (mForceSuspendActive || !mSystemReady) {
        return;
    }
    powerGroup.wakeUpLocked(eventTime, reason, details, uid, opPackageName, opUid,
            LatencyTracker.getInstance(mContext));
}
void wakeUpLocked(long eventTime, @PowerManager.WakeReason int reason, String details, int uid,
        String opPackageName, int opUid, LatencyTracker latencyTracker) {
    if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE) {
        return;
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakePowerGroup" + mGroupId);
    try {
        Slog.i(TAG, "Waking up power group from "
                + PowerManagerInternal.wakefulnessToString(mWakefulness)
                + " (groupId=" + mGroupId
                + ", uid=" + uid
                + ", reason=" + PowerManager.wakeReasonToString(reason)
                + ", details=" + details
                + ")...");
        Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, mGroupId);
        // The instrument will be timed out automatically after 2 seconds.
        latencyTracker.onActionStart(ACTION_TURN_ON_SCREEN, String.valueOf(mGroupId));

        setWakefulnessLocked(WAKEFULNESS_AWAKE, eventTime, uid, reason, opUid,
                opPackageName, details);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
}

boolean setWakefulnessLocked(int newWakefulness, long eventTime, int uid, int reason, int opUid,
        String opPackageName, String details) {
    if (mWakefulness != newWakefulness) {
        if (newWakefulness == WAKEFULNESS_AWAKE) {
            setLastPowerOnTimeLocked(eventTime);
            setIsPoweringOnLocked(true);
            mLastWakeTime = eventTime;
        } else if (isInteractive(mWakefulness) && !isInteractive(newWakefulness)) {
            mLastSleepTime = eventTime;
        }
        mWakefulness = newWakefulness;
        mWakefulnessListener.onWakefulnessChangedLocked(mGroupId, mWakefulness, eventTime,
                reason, uid, opUid, opPackageName, details);
        return true;
    }
    return false;
}
private final class PowerGroupWakefulnessChangeListener implementsPowerGroup.PowerGroupListener {
    @GuardedBy("mLock")
    @Override        
    public void onWakefulnessChangedLocked(int groupId, int wakefulness, long eventTime,                int reason, int uid, int opUid, String opPackageName, String details) {
        mWakefulnessChanging = true;
        mDirty |= DIRTY_WAKEFULNESS;
        if (wakefulness == WAKEFULNESS_AWAKE) {
            // Kick user activity to prevent newly awake group from timing out instantly.// The dream may end without user activity if the dream app crashes / is updated,// don't poke the user activity timer for these wakes.int flags = reason == PowerManager.WAKE_REASON_DREAM_FINISHED
                    ? PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0;
            userActivityNoUpdateLocked(mPowerGroups.get(groupId), eventTime,
                    PowerManager.USER_ACTIVITY_EVENT_OTHER, flags, uid);
        }
        mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS;
        mNotifier.onGroupWakefulnessChangeStarted(groupId, wakefulness, reason, eventTime);
        updateGlobalWakefulnessLocked(eventTime, reason, uid, opUid, opPackageName, details);
        updatePowerStateLocked();
    }
}

4.4 Watchdog监听 

用于检测PMS服务中是否存在死锁,超过5s,就认为PMS服务卡死,watch dog会将相关日志信息会写入dropbox和kmsg,kill system_server进程等操作。

 // PowerManagerService.java
 
 @Override
public void onStart() {
    // 加入watchdog监听
    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
}

// 在watch dog中调用,用于检测PMS服务中是否存在死锁
@Override // Watchdog.Monitor implementation
public void monitor() {
    // Grab and release lock for watchdog monitor to detect deadlocks.
    synchronized (mLock) {
    }
}


----------------------------------------------------------------------------
// Watchdog.java
public class Watchdog implements Dumpable { 
    ......
    public final class HandlerChecker implements Runnable {
    ......
        @Override
        public void run() {
            // Once we get here, we ensure that mMonitors does not change even if we call
            // #addMonitorLocked because we first add the new monitors to mMonitorQueue and
            // move them to mMonitors on the next schedule when mCompleted is true, at which
            // point we have completed execution of this method.
            final int size = mMonitors.size();
            for (int i = 0 ; i < size ; i++) {
                synchronized (mLock) {
                    mCurrentMonitor = mMonitors.get(i);
                }
                mCurrentMonitor.monitor();
            }
        
            synchronized (mLock) {
                mCompleted = true;
                mCurrentMonitor = null;
            }
        }
        ......
    }
    ......
    
    private void run() {
        boolean waitedHalf = false;

        while (true) {
            List<HandlerChecker> blockedCheckers = Collections.emptyList();
            String subject = "";
            boolean allowRestart = true;
            int debuggerWasConnected = 0;
            boolean doWaitedHalfDump = false;
            // The value of mWatchdogTimeoutMillis might change while we are executing the loop.
            // We store the current value to use a consistent value for all handlers.
            final long watchdogTimeoutMillis = mWatchdogTimeoutMillis;
            final long checkIntervalMillis = watchdogTimeoutMillis / 2;    // 5s
            final ArrayList<Integer> pids;
            synchronized (mLock) {
                long timeout = checkIntervalMillis;
                // Make sure we (re)spin the checkers that have become idle within
                // this wait-and-check interval
                // 1.启动HandlerChecker线程对PMS服务的监听
                for (int i=0; i<mHandlerCheckers.size(); i++) {
                    HandlerCheckerAndTimeout hc = mHandlerCheckers.get(i);
                    // We pick the watchdog to apply every time we reschedule the checkers. The
                    // default timeout might have changed since the last run.
                    hc.checker().scheduleCheckLocked(hc.customTimeoutMillis()
                            .orElse(watchdogTimeoutMillis * Build.HW_TIMEOUT_MULTIPLIER));
                }

                if (debuggerWasConnected > 0) {
                    debuggerWasConnected--;
                }

                // NOTE: We use uptimeMillis() here because we do not want to increment the time we
                // wait while asleep. If the device is asleep then the thing that we are waiting
                // to timeout on is asleep as well and won't have a chance to run, causing a false
                // positive on when to kill things.
                long start = SystemClock.uptimeMillis();
                while (timeout > 0) {
                    if (Debug.isDebuggerConnected()) {
                        debuggerWasConnected = 2;
                    }
                    try {
                        mLock.wait(timeout);
                        // Note: mHandlerCheckers and mMonitorChecker may have changed after waiting
                    } catch (InterruptedException e) {
                        Log.wtf(TAG, e);
                    }
                    if (Debug.isDebuggerConnected()) {
                        debuggerWasConnected = 2;
                    }
                    timeout = checkIntervalMillis - (SystemClock.uptimeMillis() - start);
                }

                final int waitState = evaluateCheckerCompletionLocked();
                if (waitState == COMPLETED) {
                    // The monitors have returned; reset
                    waitedHalf = false;
                    continue;
                } else if (waitState == WAITING) {
                    // still waiting but within their configured intervals; back off and recheck
                    continue;
                } else if (waitState == WAITED_HALF) {
                    if (!waitedHalf) {
                        Slog.i(TAG, "WAITED_HALF");
                        waitedHalf = true;
                        // We've waited half, but we'd need to do the stack trace dump w/o the lock.
                        blockedCheckers = getCheckersWithStateLocked(WAITED_HALF);
                        subject = describeCheckersLocked(blockedCheckers);
                        pids = new ArrayList<>(mInterestingJavaPids);
                        doWaitedHalfDump = true;
                    } else {
                        continue;
                    }
                } else {
                    // something is overdue!
                    blockedCheckers = getCheckersWithStateLocked(OVERDUE);
                    subject = describeCheckersLocked(blockedCheckers);
                    allowRestart = mAllowRestart;
                    pids = new ArrayList<>(mInterestingJavaPids);
                }
            } // END synchronized (mLock)

            // If we got here, that means that the system is most likely hung.
            //
            // First collect stack traces from all threads of the system process.
            //
            // Then, if we reached the full timeout, kill this process so that the system will
            // restart. If we reached half of the timeout, just log some information and continue.
            // 2.创建dropbox线程,日志信息(当前/proc/pressure/io memory cpu信息、函数调用栈信息)写入dropbox
            logWatchog(doWaitedHalfDump, subject, pids);

            if (doWaitedHalfDump) {
                // We have waited for only half of the timeout, we continue to wait for the duration
                // of the full timeout before killing the process.
                continue;
            }

            IActivityController controller;
            synchronized (mLock) {
                controller = mController;
            }
            if (controller != null) {
                Slog.i(TAG, "Reporting stuck state to activity controller");
                try {
                    Binder.setDumpDisabled("Service dumps disabled due to hung system process.");
                    // 1 = keep waiting, -1 = kill system
                    int res = controller.systemNotResponding(subject);
                    if (res >= 0) {
                        Slog.i(TAG, "Activity controller requested to coninue to wait");
                        waitedHalf = false;
                        continue;
                    }
                } catch (RemoteException e) {
                }
            }

            // Only kill the process if the debugger is not attached.
            if (Debug.isDebuggerConnected()) {
                debuggerWasConnected = 2;
            }
            if (debuggerWasConnected >= 2) {
                Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
            } else if (debuggerWasConnected > 0) {
                Slog.w(TAG, "Debugger was connected: Watchdog is *not* killing the system process");
            } else if (!allowRestart) {
                Slog.w(TAG, "Restart not allowed: Watchdog is *not* killing the system process");
            } else {
                Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + subject);
                WatchdogDiagnostics.diagnoseCheckers(blockedCheckers);
                Slog.w(TAG, "*** GOODBYE!");
                if (!Build.IS_USER && isCrashLoopFound()
                        && !WatchdogProperties.should_ignore_fatal_count().orElse(false)) {
                    // 3."Fatal reset to escape the system_server crashing loop\n"字符串
                    // 写入/dev/kmsg_debug
                    breakCrashLoop();
                }
                // 4.kill system_server进程
                Process.killProcess(Process.myPid());
                System.exit(10);
            }

            waitedHalf = false;
        }
    }
   ......
   
   }

总结---

Watch dog工作原理:

1)启动HandlerChecker线程对PMS服务的监听(默认超过5s认为是死锁)

2)PMS服务出现死锁,创建dropbox线程,日志信息(当前/proc/pressure/io memory cpu信息、函数调用栈信息)写入dropbox

3)"Fatal reset to escape the system_server crashing loop\n"字符串写入/dev/kmsg_debug

4)kill system_server进程

4.5 关机流程

其它模块调用reboot binder api,执行ShutdownThread线程的reboot或shutdown接口,做重启或关机操作。

@Override // Binder call
public void reboot(boolean confirm, @Nullable String reason, boolean wait) {
    mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
    if (PowerManager.REBOOT_RECOVERY.equals(reason)
            || PowerManager.REBOOT_RECOVERY_UPDATE.equals(reason)) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
    }

    ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
    final long ident = Binder.clearCallingIdentity();
    try {
        shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait);
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}

private void shutdownOrRebootInternal(final @HaltMode int haltMode, final boolean confirm,
        @Nullable final String reason, boolean wait) {
    if (PowerManager.REBOOT_USERSPACE.equals(reason)) {
        if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
            throw new UnsupportedOperationException(
                    "Attempted userspace reboot on a device that doesn't support it");
        }
        UserspaceRebootLogger.noteUserspaceRebootWasRequested();
    }
    if (mHandler == null || !mSystemReady) {
        if (RescueParty.isAttemptingFactoryReset()) {
            // If we're stuck in a really low-level reboot loop, and a
            // rescue party is trying to prompt the user for a factory data
            // reset, we must GET TO DA CHOPPA!
            // No check point from ShutdownCheckPoints will be dumped at this state.
            PowerManagerService.lowLevelReboot(reason);
        } else {
            throw new IllegalStateException("Too early to call shutdown() or reboot()");
        }
    }

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            synchronized (this) {
                if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) {
                    ShutdownThread.rebootSafeMode(getUiContext(), confirm);
                } else if (haltMode == HALT_MODE_REBOOT) {
                    ShutdownThread.reboot(getUiContext(), reason, confirm);
                } else {
                    ShutdownThread.shutdown(getUiContext(), reason, confirm);
                }
            }
        }
    };

    // ShutdownThread must run on a looper capable of displaying the UI.
    // 关机操作必须在一个看得见的UI线程上执行
    Message msg = Message.obtain(UiThread.getHandler(), runnable);
    msg.setAsynchronous(true);
    UiThread.getHandler().sendMessage(msg);

    // PowerManager.reboot() is documented not to return so just wait for the inevitable.
    if (wait) {
        synchronized (runnable) {
            while (true) {
                try {
                    runnable.wait();
                } catch (InterruptedException e) {
                }
            }
        }
    }
}

 4.6 Device Doze or Idle mode

1)涉及device doze机制相关的代码

将Android Doze调用该API,将Doze白名单传给PMS,当设备处于device idle或standby模式下,将非Doze或非Standby白名单中的app的wakelock进行disable处理。

@Override
public void setDeviceIdleWhitelist(int[] appids) {
    setDeviceIdleWhitelistInternal(appids);
}

void setDeviceIdleWhitelistInternal(int[] appids) {
    synchronized (mLock) {
        mDeviceIdleWhitelist = appids;
        if (mDeviceIdleMode) {
            updateWakeLockDisabledStatesLocked();
        }
    }
}

// 更新wakelock disable状态
@GuardedBy("mLock")
private void updateWakeLockDisabledStatesLocked() {
    boolean changed = false;
    final int numWakeLocks = mWakeLocks.size();
    for (int i = 0; i < numWakeLocks; i++) {
        final WakeLock wakeLock = mWakeLocks.get(i);
        // 判断是否为PARTIAL_WAKE_LOCK或亮屏锁
        if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
                == PowerManager.PARTIAL_WAKE_LOCK || isScreenLock(wakeLock)) {
             // 将wakelock状态设置为disable
            if (setWakeLockDisabledStateLocked(wakeLock)) {
                changed = true;
                if (wakeLock.mDisabled) {
                    // This wake lock is no longer being respected.
                    notifyWakeLockReleasedLocked(wakeLock);
                } else {
                    notifyWakeLockAcquiredLocked(wakeLock);
                }
            }
        }
    }
    if (changed) {
        mDirty |= DIRTY_WAKE_LOCKS;
        updatePowerStateLocked();
    }
}

// 根据当前设备所处的模式,将非Doze或非Standby白名单中的app的wakelock进行disable处理
@GuardedBy("mLock")
private boolean setWakeLockDisabledStateLocked(WakeLock wakeLock) {
    if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
            == PowerManager.PARTIAL_WAKE_LOCK) {
        boolean disabled = false;
        final int appid = UserHandle.getAppId(wakeLock.mOwnerUid);
        // FIRST_APPLICATION_UID为10000,> 10000的分配给app进程
        if (appid >= Process.FIRST_APPLICATION_UID) {
            // Cached inactive processes are never allowed to hold wake locks.
            // 禁止非活跃状态的cache进程持有唤醒锁
            if (mConstants.NO_CACHED_WAKE_LOCKS) {
                disabled = mForceSuspendActive
                        || (!wakeLock.mUidState.mActive && wakeLock.mUidState.mProcState
                                != ActivityManager.PROCESS_STATE_NONEXISTENT &&
                        wakeLock.mUidState.mProcState > ActivityManager.PROCESS_STATE_RECEIVER);
            }
            // 如果设备处于device idle模式,忽略非Doze白名单中的app的wakelock
            if (mDeviceIdleMode) {
                // If we are in idle mode, we will also ignore all partial wake locks that are
                // for application uids that are not allowlisted.
                final UidState state = wakeLock.mUidState;
                if (Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
                        Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
                        state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT &&
                        state.mProcState >
                                ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
                    disabled = true;
                }
            }
            // 如果设备处于LowPowerStandbyActive模式,忽略非Standby白名单中的app的wakelock
            if (mLowPowerStandbyActive) {
                final UidState state = wakeLock.mUidState;
                if (Arrays.binarySearch(mLowPowerStandbyAllowlist, wakeLock.mOwnerUid) < 0
                        && state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT
                        && state.mProcState > ActivityManager.PROCESS_STATE_BOUND_TOP) {
                    disabled = true;
                }
            }
        }
        return wakeLock.setDisabled(disabled);
    } else if (mDisableScreenWakeLocksWhileCached && isScreenLock(wakeLock)) {
        boolean disabled = false;
        final int appid = UserHandle.getAppId(wakeLock.mOwnerUid);
        final UidState state = wakeLock.mUidState;
        // Cached inactive processes are never allowed to hold wake locks.
        if (mConstants.NO_CACHED_WAKE_LOCKS
                && appid >= Process.FIRST_APPLICATION_UID
                && !state.mActive
                && state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT
                && state.mProcState >= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
            if (DEBUG_SPEW) {
                Slog.d(TAG, "disabling full wakelock " + wakeLock);
            }
            disabled = true;
        }
        return wakeLock.setDisabled(disabled);
    }
    return false;
}

2)设置device idle模式

PMS提供设置device idle mode的接口,然后通过power hal将该模式写入"/power/mode"节点,device idle模式下,设备频率电压会降低或关闭设备,达到节省功耗的目的。

@Override
public boolean setDeviceIdleMode(boolean enabled) {
    return setDeviceIdleModeInternal(enabled);
}

boolean setDeviceIdleModeInternal(boolean enabled) {
    synchronized (mLock) {
        if (mDeviceIdleMode == enabled) {
            return false;
        }
        mDeviceIdleMode = enabled;
        updateWakeLockDisabledStatesLocked();
        setPowerModeInternal(MODE_DEVICE_IDLE, mDeviceIdleMode || mLightDeviceIdleMode);
    }
    if (enabled) {
        EventLogTags.writeDeviceIdleOnPhase("power");
    } else {
        EventLogTags.writeDeviceIdleOffPhase("power");
    }
    return true;
}

private boolean setPowerModeInternal(int mode, boolean enabled) {
    // Maybe filter the event.
    if (mode == Mode.LAUNCH && enabled && mBatterySaverController.isLaunchBoostDisabled()) {
        return false;
    }
    return mNativeWrapper.nativeSetPowerMode(mode, enabled);
}

// /com_android_server_power_PowerManagerService.cpp
static power::PowerHalController gPowerHalController;

static jboolean nativeSetPowerMode(JNIEnv* /* env */, jclass /* clazz */, jint mode,
                                   jboolean enabled) {
    return setPowerMode(static_cast<Mode>(mode), enabled);
}

static bool setPowerMode(Mode mode, bool enabled) {
    android::base::Timer t;
    auto result = gPowerHalController.setMode(mode, enabled);
    if (mode == Mode::INTERACTIVE && t.duration() > 20ms) {
        ALOGD("Excessive delay in setting interactive mode to %s while turning screen %s",
              enabled ? "true" : "false", enabled ? "on" : "off");
    }
    return result.isOk();
}

// power hal
ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
    LOG(VERBOSE) << "Power setMode: " << static_cast<int32_t>(type) << " to: " << enabled;

    int32_t param = 1;
    int32_t hint = static_cast<int32_t>(type);

    if (type == Mode::INTERACTIVE) {
        if (mModule->setInteractive)
            mModule->setInteractive(mModule, enabled ? 1 : 0);

        return ndk::ScopedAStatus::ok();
    }

    if (hint < VENDOR_PERF_ID_BASE) {
        hint = hint + MODE_PERF_ID_MAPPING;
    }

    if (mModule->powerHint) {
        if (enabled)
            mModule->powerHint(mModule, static_cast<power_hint_t>(hint), &param);
        else
            mModule->powerHint(mModule, static_cast<power_hint_t>(hint), NULL);
    }

    return ndk::ScopedAStatus::ok();
}

static void xxx_power_hint(struct xxx_power_module *module, power_hint_t hint,
                             void *data)
{
    struct xxx_power_module *pm = (struct xxx_power_module *)module;
    static bool is_launching = false;

    if (CC_UNLIKELY(power_hint_enable == 0)) return;

    ALOGD_IF(DEBUG_V, "Enter %s:(%d:%d)", __func__, hint, ((data!=NULL)?(*(int*)data):0));
    pthread_mutex_lock(&pm->lock);
    if (CC_UNLIKELY(!pm->init_done)) {
        pthread_mutex_unlock(&pm->lock);
        ALOGE("%s: power hint is not inited", __func__);
        return;
    }

    int duration = 0;

    if (data != NULL) {
        duration = *((int*)data) & 0xffff;
        if (duration == 1 || duration == 0) {
            duration = 0;
        } else if (duration < BOOST_DURATION_DEFAULT || duration > BOOST_DURATION_MAX) {
            duration = BOOST_DURATION_DEFAULT;
        }
    }
    // 最后写入 "/power/mode"节点
    boost(hint, 0, ((data != NULL)? 1: 0), duration);

    pthread_mutex_unlock(&pm->lock);
    ALOGD_IF(DEBUG_V, "Exit %s:(%d:%d)", __func__, hint, ((data!=NULL)?(*(int*)data):0));
}

4.7 监控长时间持锁行为

PMS监控应用或模块长时间持锁行为,

void checkForLongWakeLocks() {
    synchronized (mLock) {
        final long now = mClock.uptimeMillis();
        mNotifyLongDispatched = now;
        final long when = now - MIN_LONG_WAKE_CHECK_INTERVAL;
        long nextCheckTime = Long.MAX_VALUE;
        final int numWakeLocks = mWakeLocks.size();
        // 遍历wakelock列表,如果wakelock超过持锁时间60s,则notify。否则,找到最小的nextCheckTime,
        // 如,wakelock1持锁40s,wakelock2持锁50s,
        // 则下一次检测持锁时间nextCheckTime为wakelock2开始持锁时间点+ 60s
        for (int i = 0; i < numWakeLocks; i++) {
            final WakeLock wakeLock = mWakeLocks.get(i);
            if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
                    == PowerManager.PARTIAL_WAKE_LOCK) {
                if (wakeLock.mNotifiedAcquired && !wakeLock.mNotifiedLong) {
                    // 持锁时间超过MIN_LONG_WAKE_CHECK_INTERVAL (60s),notify
                    if (wakeLock.mAcquireTime < when) {
                        // This wake lock has exceeded the long acquire time, report!
                        notifyWakeLockLongStartedLocked(wakeLock);
                    } else {
                        // This wake lock could still become a long one, at this time.
                        // 更新下一次检测wakelock持锁时长
                        long checkTime = wakeLock.mAcquireTime + MIN_LONG_WAKE_CHECK_INTERVAL;
                        if (checkTime < nextCheckTime) {
                            nextCheckTime = checkTime;
                        }
                    }
                }
            }
        }
        mNotifyLongScheduled = 0;
        // 从handler消息队列中删除MSG_CHECK_FOR_LONG_WAKELOCKS,然后重新加入
        mHandler.removeMessages(MSG_CHECK_FOR_LONG_WAKELOCKS);
        if (nextCheckTime != Long.MAX_VALUE) {
            mNotifyLongNextCheck = nextCheckTime;
            enqueueNotifyLongMsgLocked(nextCheckTime);
        } else {
            mNotifyLongNextCheck = 0;
        }
    }
}

// MSG_CHECK_FOR_LONG_WAKELOCKS时间加入handler消息队列,并在nextCheckTime后出发
 @GuardedBy("mLock")
private void enqueueNotifyLongMsgLocked(long time) {
    mNotifyLongScheduled = time;
    Message msg = mHandler.obtainMessage(MSG_CHECK_FOR_LONG_WAKELOCKS);
    msg.setAsynchronous(true);
    mHandler.sendMessageAtTime(msg, time);
}

// nextCheckTime后,取出并处理消息队列中的MSG_CHECK_FOR_LONG_WAKELOCKS信息,执行checkForLongWakeLocks方法
private final class PowerManagerHandlerCallback implements Handler.Callback {
    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_USER_ACTIVITY_TIMEOUT:
                handleUserActivityTimeout();
                break;
            case MSG_SANDMAN:
                handleSandman(msg.arg1);
                break;
            case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
                handleScreenBrightnessBoostTimeout();
                break;
            case MSG_CHECK_FOR_LONG_WAKELOCKS:
                checkForLongWakeLocks();
                break;
            case MSG_ATTENTIVE_TIMEOUT:
                handleAttentiveTimeout();
                break;
        }

        return true;
    }
}

待改进点:

1)下一次检测持锁时间:当前是nextCheckTime为wakelock开始持锁时间点+ 60s,可以改成nextCheckTime为60s - 当前的时间点。如,某个wakelock持锁时长为40s,还未超过60s,则下一次检测持锁时间为20s后。

2)可以增加对模块长时间持锁是否为异常行为的判断机制,如audio app长时间持锁,但不持有Audio focus、没有对应可执行的struct task等为异常行为,对异常持锁行为进行管理与优化

五、PMS服务核心参数

// 1.电源状态发生变化的参数
// Dirty bit: mWakeLocks changed
private static final int DIRTY_WAKE_LOCKS = 1 << 0;
// Dirty bit: mWakefulness changed
private static final int DIRTY_WAKEFULNESS = 1 << 1;
// Dirty bit: user activity was poked or may have timed out
private static final int DIRTY_USER_ACTIVITY = 1 << 2;
// Dirty bit: actual display power state was updated asynchronously
private static final int DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED = 1 << 3;
// Dirty bit: mBootCompleted changed
private static final int DIRTY_BOOT_COMPLETED = 1 << 4;
// Dirty bit: settings changed
private static final int DIRTY_SETTINGS = 1 << 5;
// Dirty bit: mIsPowered changed
private static final int DIRTY_IS_POWERED = 1 << 6;
// Dirty bit: mStayOn changed
private static final int DIRTY_STAY_ON = 1 << 7;
// Dirty bit: battery state changed
private static final int DIRTY_BATTERY_STATE = 1 << 8;
// Dirty bit: proximity state changed
private static final int DIRTY_PROXIMITY_POSITIVE = 1 << 9;
// Dirty bit: dock state changed
private static final int DIRTY_DOCK_STATE = 1 << 10;
// Dirty bit: brightness boost changed
private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11;
// Dirty bit: sQuiescent changed
private static final int DIRTY_QUIESCENT = 1 << 12;
// Dirty bit: attentive timer may have timed out
private static final int DIRTY_ATTENTIVE = 1 << 14;
// Dirty bit: display group wakefulness has changed
private static final int DIRTY_DISPLAY_GROUP_WAKEFULNESS = 1 << 16;

// 2.wakelock类型
 // Summarizes the state of all active wakelocks.
static final int WAKE_LOCK_CPU = 1 << 0;
static final int WAKE_LOCK_SCREEN_BRIGHT = 1 << 1;
static final int WAKE_LOCK_SCREEN_DIM = 1 << 2;
static final int WAKE_LOCK_BUTTON_BRIGHT = 1 << 3;
static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
static final int WAKE_LOCK_DOZE = 1 << 6;
static final int WAKE_LOCK_DRAW = 1 << 7;

// 3.用户活动状态参数
// Summarizes the user activity state.
static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;    // 屏幕高亮
static final int USER_ACTIVITY_SCREEN_DIM = 1 << 1;    // 屏幕昏暗
static final int USER_ACTIVITY_SCREEN_DREAM = 1 << 2;    // 屏幕进入屏保

// 4.设备关机原生的参数
 // Possible reasons for shutting down or reboot for use in
 // SYSTEM_PROPERTY_REBOOT_REASON(sys.boot.reason) which is set by bootstatprivate static final String REASON_SHUTDOWN = "shutdown";
private static final String REASON_REBOOT = "reboot";
private static final String REASON_USERREQUESTED = "shutdown,userrequested";
private static final String REASON_THERMAL_SHUTDOWN = "shutdown,thermal";
private static final String REASON_LOW_BATTERY = "shutdown,battery";
private static final String REASON_BATTERY_THERMAL_STATE = "shutdown,thermal,

六、核心API

6.1 核心private API

6.1.1 updatePowerStateLocked

updatePowerStateLocked接口基于mDirty状态值更新电源状态。

电源状态更新的场景:

1)设备唤醒状态发生变化---onWakefulnessChangedLocked

2)完成开机---onBootPhase

3)systemReady初始化阶段---systemReady

4)系统设置发生变化---handleSettingsChangedLocked

5)申请wakelock---acquireWakeLockInternal

6)释放wakelock---removeWakeLockLocked

7)用户活动状态发生变化---userActivityInternal

8)display发生变化

9)电池状态发生变化---handleBatteryStateChangedLocked

10)屏幕亮度状态发生变化

11)屏保状态发生变化

12)wakelock状态发生变化---updateWakeLockDisabledStatesLocked

13)dock状态发生变化

14)设备唤醒状态发生变化---wakeUp

/**
 * Updates the global power state based on dirty bits recorded in mDirty.
 *
 * This is the main function that performs power state transitions.
 * We centralize them here so that we can recompute the power state completely
 * each time something important changes, and ensure that we do it the same
 * way each time.  The point is to gather all of the transition logic here.
 */
@GuardedBy("mLock")
private void updatePowerStateLocked() {
    // mDirty状态值为0,无需更新电源状态
    if (!mSystemReady || mDirty == 0 || mUpdatePowerStateInProgress) {
        return;
    }
    if (!Thread.holdsLock(mLock)) {
        Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
    mUpdatePowerStateInProgress = true;
    try {
        // Phase 0: Basic state updates.
        // 基础状态更新
        updateIsPoweredLocked(mDirty);    // 更新电池状态、充电器类型、电池电量等信息
        updateStayOnLocked(mDirty);    // 更新设备的待机状态
        updateScreenBrightnessBoostLocked(mDirty);    // 更新屏幕亮度增强状态

        // Phase 1: Update wakefulness.
        // Loop because the wake lock and user activity computations are influenced
        // by changes in wakefulness.
        // 更新设备休眠唤醒状态
        final long now = mClock.uptimeMillis();
        int dirtyPhase2 = 0;
        for (;;) {
            int dirtyPhase1 = mDirty;
            dirtyPhase2 |= dirtyPhase1;
            mDirty = 0;

            updateWakeLockSummaryLocked(dirtyPhase1);    // 更新所有活动唤醒锁的状态
            updateUserActivitySummaryLocked(now, dirtyPhase1);    // 更新用户活动状态
            updateAttentiveStateLocked(now, dirtyPhase1);    // 更新用户提示状态,如低电量
            // 更新设备休眠唤醒状态
            if (!updateWakefulnessLocked(dirtyPhase1)) {
                break;
            }
        }
        
        // Phase 2: Lock profiles that became inactive/not kept awake.
        // 更新User ID、屏幕关闭超时时间和当前时间
        updateProfilesLocked(now);

        // Phase 3: Update power state of all PowerGroups.
        final boolean powerGroupsBecameReady = updatePowerGroupsLocked(dirtyPhase2);

        // Phase 4: Update dream state (depends on power group ready signal).
        // 更新屏保状态
        updateDreamLocked(dirtyPhase2, powerGroupsBecameReady);

        // Phase 5: Send notifications, if needed.
        // 向其他组件发出设备休眠与唤醒状态切换的通知
        finishWakefulnessChangeIfNeededLocked();

        // Phase 6: Update suspend blocker.
        // Because we might release the last suspend blocker here, we need to make sure
        // we finished everything else first!
        // 更新系统的wakelock
        updateSuspendBlockerLocked();
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
        mUpdatePowerStateInProgress = false;
    }
}

6.1.2 userActivityNoUpdateLocked

处理用户活动事件,如屏幕触摸、按键等。根据条件判断确定能否处理用户活动,然后根据事件时间、事件类型等信息更新相应的状态。

private boolean userActivityNoUpdateLocked(final PowerGroup powerGroup, long eventTime,
        @PowerManager.UserActivityEvent int event, int flags, int uid) {
    final int groupId = powerGroup.getGroupId();
    if (DEBUG_SPEW) {
        Slog.d(TAG, "userActivityNoUpdateLocked: groupId=" + groupId
                + ", eventTime=" + eventTime
                + ", event=" + PowerManager.userActivityEventToString(event)
                + ", flags=0x" + Integer.toHexString(flags) + ", uid=" + uid);
    }

    if (eventTime < powerGroup.getLastSleepTimeLocked()
            || eventTime < powerGroup.getLastWakeTimeLocked() || !mSystemReady) {
        return false;
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "userActivity");
    try {
        if (eventTime > mLastInteractivePowerHintTime) {
            setPowerBoostInternal(Boost.INTERACTION, 0);
            mLastInteractivePowerHintTime = eventTime;
        }

        mNotifier.onUserActivity(powerGroup.getGroupId(), event, uid);
        mAttentionDetector.onUserActivity(eventTime, event);

        if (mUserInactiveOverrideFromWindowManager) {
            mUserInactiveOverrideFromWindowManager = false;
            mOverriddenTimeout = -1;
        }
        final int wakefulness = powerGroup.getWakefulnessLocked();
        if (wakefulness == WAKEFULNESS_ASLEEP
                || wakefulness == WAKEFULNESS_DOZING
                || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
            return false;
        }

        maybeUpdateForegroundProfileLastActivityLocked(eventTime);

        if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
            if (eventTime > powerGroup.getLastUserActivityTimeNoChangeLightsLocked()
                    && eventTime > powerGroup.getLastUserActivityTimeLocked()) {
                powerGroup.setLastUserActivityTimeNoChangeLightsLocked(eventTime, event);
                mDirty |= DIRTY_USER_ACTIVITY;
                if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
                    mDirty |= DIRTY_QUIESCENT;
                }

                return true;
            }
        } else {
            if (eventTime > powerGroup.getLastUserActivityTimeLocked()) {
                powerGroup.setLastUserActivityTimeLocked(eventTime, event);
                mDirty |= DIRTY_USER_ACTIVITY;
                if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
                    mDirty |= DIRTY_QUIESCENT;
                }
                return true;
            }
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return false;
}

6.2 Binder API

BinderService继承IPowerManager.Stub(由IPowerManager.aidl编译生成的binder框架代码),提供Binder API.

其它模块可以通过PowerManager mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);获取PowerManager对象,然后通过该对象获取PMS中的Binder API.

Binder接口

作用

1

acquireWakeLockWithUid

申请wakelock,需传入app的uid,其uid封装到wakesource对象

2

setPowerBoost

cpu提频

3

setPowerMode

设置设备模式,如device idle、performance等

4

setPowerModeChecked

设置设备模式,如device idle、performance等,且当PMS服务还未system ready,返回false

5

acquireWakeLock

申请wakelock

6

acquireWakeLockAsync

异步方式申请wakelock

7

releaseWakeLock

释放wakelock

8

releaseWakeLockAsync

异步方式释放wakelock

9

updateWakeLockUids

更新某应用的wakelock

10

updateWakeLockUidsAsync

异步方式申请wakelock

11

updateWakeLockWorkSource

更新某个wakelock的WorkSource

12

updateWakeLockCallback

更新某个wakelock的Callback对象

13

isWakeLockLevelSupported

判断申请的wakelock类型是否可用

14

userActivity

当设备接收到用户活动事件,例如按下按钮、触摸屏幕或使用键盘时,该方法会根据用户的操作来更新相关的电源状态

15

wakeUp

唤醒系统

16

goToSleep

系统进入休眠

17

goToSleepWithDisplayId

系统进入休眠,并传入DisplayId信息

18

nap

屏幕进入屏保状态

19

isInteractive

判断设备是否处于用户活动状态,如用户触摸屏幕、按键事件等

20

isDisplayInteractive

根据特定显示和给定的用户 ID 来判断是否处于互动状态

21

areAutoPowerSaveModesEnabled

在配置文件中获取省电模式是否默认使能

22

isPowerSaveMode

判断省电模式得功能是否使能

23

getPowerSaveState

获取不同场景下的省电策略,如app standby场景下,所有app进入standby模式

24

setPowerSaveModeEnabled

省电策略使能

25

getFullPowerSavePolicy

获取所有的电池节能策略

26

setFullPowerSavePolicy

设置整个电池节能策略

27

setDynamicPowerSaveHint

设置动态地调整电池的使用策略。根据设备的使用情况动态地调整电池的使用策略,以实现更有效的电池管理和延长电池寿命。

28

setAdaptivePowerSavePolicy

设置自适应省电策略。可以根据设备的使用情况和用户习惯动态地调整电池的使用策略

29

setAdaptivePowerSaveEnabled

用于设置是否启用自适应省电模式

30

getPowerSaveModeTrigger

从settings中获取触发省电模式开关的值

31

setBatteryDischargePrediction

不充电环境下,设置对设备的电池消耗预测

32

getBatteryDischargePrediction

不充电环境下,获取对设备的电池消耗预测

33

isBatteryDischargePredictionPersonalized

电池放电预测个性化功能是否打开。在电池放电预测个性化,是针对每个用户的独特使用模式和习惯进行定制化的预测

34

isDeviceIdleMode

判断设备是否进入device idle模式

35

isLightDeviceIdleMode

同上

36

isLowPowerStandbySupported

判断是否支持standby省电模式

37

isLowPowerStandbyEnabled

判断standby省电模式功能开关是否打开

38

setLowPowerStandbyEnabled

设置standby省电模式功能使能

39

setLowPowerStandbyActiveDuringMaintenance

在Maintenance阶段,设置standby省电模式功能使能

40

forceLowPowerStandbyActive

强制进入standby省电模式

41

setLowPowerStandbyPolicy

设置standby模式的省电策略

42

getLowPowerStandbyPolicy

获取standby模式的省电策略

43

isExemptFromLowPowerStandby

判断该app是否免除进入低功耗待机模式

44

isReasonAllowedInLowPowerStandby

检测在低功耗待机模式中是否被允许执行

45

isFeatureAllowedInLowPowerStandby

检查给定特性是否在低功耗待机模式下被允许

46

acquireLowPowerStandbyPorts

低功耗待机(standby)模式下的端口用于在设备进入低功耗待机模式时保持一些特定服务或功能的连接或开放。在低功耗待机模式下,设备会关闭或限制某些后台操作。然而,有一些服务或功能可能仍然需要保持活动状态,以便能够及时提供必要的功能或服务。

47

releaseLowPowerStandbyPorts

释放低功耗待机模式下的端口

48

getActiveLowPowerStandbyPorts

获取低功耗待机模式下的端口

49

getLastShutdownReason

获取上次进入系统关机的原因

50

getLastSleepReason

获取上次进入系统睡眠的原因

51

reboot

系统重启。系统重启是指将设备重新启动,关闭当前的运行进程和服务,然后重新启动整个系统。这通常会导致设备重新加载所有组件并恢复到初始状态。

52

rebootSafeMode

系统在安全模式下重启。安全模式下,设备会以最小化的配置和功能启动,只加载必需的系统组件和驱动程序,并禁用所有第三方应用和扩展。它的目的是让用户在安全模式下排除可能导致设备问题的第三方应用或驱动程序,以便诊断和修复系统故障。

53

shutdown

系统关机

54

crash

调用该接口,会使整个system_server进程crash,然后重启system_server

55

setStayOnSetting

插入特定电源充电(如USB)时,即使用户没有进行操作,设备仍然保持亮屏状态,不自动进入休眠或待机模式。这通常用于特定的应用场景,如在展示设备、信息显示屏等需要持续工作的环境中。

56

setAttentionLight

当来电话时,设置LED灯闪烁功能开关设置

57

setDozeAfterScreenOff

灭屏后进入Doze状态的功能开关设置

58

isAmbientDisplayAvailable

用于检查Ambient Display功能是否可用

59

suppressAmbientDisplay

控制Ambient Display功能使能

60

isAmbientDisplaySuppressedForToken

检查Ambient Display功能的是否使能

61

isAmbientDisplaySuppressedForTokenByApp

同上

62

isAmbientDisplaySuppressed

同上

63

boostScreenBrightness

增加屏幕亮度

64

isScreenBrightnessBoosted

判断是否正处于屏幕亮度增强阶段

65

forceSuspend

强制进入系统休眠,忽略系统中的保持cpu唤醒的wakelock

66

dump

dump进程的调用接口,可以set\get操作

6.3 Local API

PMS提供给System_server进程中其它服务或组件的进程内部API.

其它模块可以通过PowerManagerInternal mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);获取PowerManagerInternal 对象,通过该对象获取到Local API.

本地接口

作用

1

setScreenBrightnessOverrideFromWindowManager

设置屏幕亮度值

2

setDozeOverrideFromDreamManager

设置Display状态(包括ON\OFF\DOZE\DOZE_SUPEND\ON_SUSPEND)及屏幕亮度值

3

setUserInactiveOverrideFromWindowManager

设置用户为非活动状态

4

setUserActivityTimeoutOverrideFromWindowManager

设置foreground activity覆盖用户活动超时时间的功能,前台应用需要保持屏幕保持唤醒状态,以便持续显示内容或响应用户的操作

5

setDrawWakeLockOverrideFromSidekick

控制设备在doze(设备休眠)状态下是否保持屏幕的显示状态

6

setMaximumScreenOffTimeoutFromDeviceAdmin

设置屏幕关闭的最大超时时间

7

getLowPowerState

根据场景,获取该场景下的省电策略参数,封装到PowerSaveState对象返回。如app standby场景下,所有app进入standby模式

8

registerLowPowerModeObserver

注册低电量模式监听广播

9

setDeviceIdleMode

设置设备为device idle模式,通过power hal向"/power/mode"写节点

10

setLightDeviceIdleMode

同上

11

setDeviceIdleWhitelist

Doze模块向PMS传递xml默认Doze白名单

12

setDeviceIdleTempWhitelist

Doze模块向PMS传递用户设置Doze白名单

13

setLowPowerStandbyAllowlist

设置app standby模式下的白名单

14

setLowPowerStandbyActive

设置app standby模式状态

15

startUidChanges

开始更改用户ID

16

finishUidChanges

结束更改用户ID

17

updateUidProcState

更新某个UID下的进程状态

18

uidGone

某个app或其它模块被卸载,从mUidState列表中移除该UID号

19

uidActive

某个app或其它模块被安装,从mUidState列表中加入该UID号

20

uidIdle

某个app或其它模块进入idle状态,对其state更新为Active为false状态

21

setPowerBoost

cpu提频

22

setPowerMode

设置设备模式,如device idle、performance等

23

wasDeviceIdleFor

判断设备是否在指定的时间段内处于空闲状态

24

getLastWakeup

获取上一次设备被唤醒的原因及时间点

25

getLastGoToSleep

获取上一次设备进入睡眠的原因及时间点

26

interceptPowerKeyDown

如果侦测到屏幕关闭时启用的接近传感器(proximity sensor),则告诉显示管理器忽略接近传感器,从而重新打开屏幕

27

nap

屏幕进入屏保状态

28

isAmbientDisplaySuppressed

该方法用于检测该功能被关闭。Ambient Display可以在Android设备的待机状态下,通过点亮部分屏幕或显示简洁的信息来提醒用户有新的通知或消息。它提供了一种无需解锁手机即可查看最新通知的便捷方式。

  • 50
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
调通sina33下的AP6212A0版本的BT 大文实验室/大文哥 壹捌陆捌零陆捌捌陆捌贰 wb4916 AT qq.com 完成时间:2017/6/26 11:01 版本:V1.0 本文参照: 《A33 wifi移植说明书.pdf》 还有就是全志R16的parrotv1.1的官方SDK(Android4.4.2) 1、打开AP6212的BT,关闭rtl8723bs的BT: [ 3.141273] Bluetooth: HCI UART driver ver 2.2 [ 3.146210] Bluetooth: HCI H4 protocol initialized [ 3.151563] Bluetooth: HCI BCSP protocol initialized [ 3.157154] usbcore: registered new interface driver btusb [ 3.163282] Bluetooth: Generic Bluetooth SDIO driver ver 0.1 [ 3.169599] Bluetooth: BlueSleep Mode Driver Ver 1.1 [ 3.175402] Bluetooth: get rtl8723bs rtl8723bs_bt_host_wake gpio failed [ 3.953017] Bluetooth: RFCOMM TTY layer initialized [ 3.958456] Bluetooth: RFCOMM socket layer initialized [ 3.964183] Bluetooth: RFCOMM ver 1.11 [ 3.968340] Bluetooth: BNEP (Ethernet Emulation) ver 1.3 [ 3.968638] [mmc]: sdc2 set ios: clk 25000000Hz bm PP pm ON vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 3.968734] [mmc]: mclk 0xf1c20090 0xc100000b [ 3.989421] Bluetooth: BNEP filters: protocol multicast [ 3.995242] Bluetooth: HIDP (Human Interface Emulation) ver 1.2 [ 4.001921] L2TP core driver, V2.0 [ 4.005706] PPPoL2TP kernel driver, V2.0 [ 4.010070] L2TP IP encapsulation support (L2TPv3) [ 4.015468] L2TP netlink interface [ 4.019264] L2TP ethernet pseudowire support (L2TPv3) [ 4.023860] [mmc]: sdc2 set ios: clk 25000000Hz bm PP pm ON vdd 3.3V width 1 timing MMC-HS(SDR20) dt B [ 4.023929] [mmc]: mclk 0xf1c20090 0xc100000b [ 4.040272] VFP support v0.3: implementor 41 architecture 2 part 30 variant 7 rev 5 [ 4.048780] ThumbEE CPU extension supported. [ 4.053550] Registering SWP/SWPB emulation handler [ 4.059269] [rfkill]: rfkill set power 1 [ 4.063652] gpio ap6xxx_bt_regon set val 0, act val 0 正常启动的BT加载: [ 3.207764] Bluetooth: HCI UART driver ver 2.2 [ 3.212725] Bluetooth: HCI H4 protocol initialized [ 3.218045] Bluetooth: HCI BCSP protocol initialized [ 3.223671] usbcore: registered new interface driver btusb [ 3.229766] Bluetooth: Generic Bluetooth SDIO driver ver 0.1 [ 3.236243] Bluetooth: MSM Sleep Mode Driver Ver 1.2 rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r$ ll rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ ./build.sh config Welcome to mkscript setup progress All available chips: 0. sun8iw5p1 Choice: 0 All available platforms: 0. android 1. dragonboard 2. linux Choice: 0 All available kernel: 0. linux-3.4 Choice: 0 All available boards: 0. evb 1. maple 2. redwood 3. y2 4. y3 Choice: 4 rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ cd linux-3.4/ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4$ make ARCH=arm menuconfig [*] Networking support ---> Bluetooth subsystem support ---> Bluetooth device drivers ---> Broadcom Bluetooth Low Power Manager Support Realtek Bluesleep driver support 修改为: Broadcom Bluetooth Low Power Manager Support An inverter between bt hostwake pin and cpu (NEW) Realtek Bluesleep driver support 2、(这个不修改:) R:\wyb\ap6212a0_a33_sc3817r\android\device\softwinner\astar-y3\overlay\frameworks\base\core\res\res\values\config.xml "wlan0" "bt-pan" 3、 R:\wyb\ap6212a0_a33_sc3817r\android\device\softwinner\astar-y3\astar_y3.mk # ap6181/6210/6330 sdio wifi fw and nvram #$(call inherit-product-if-exists, hardware/broadcom/wlan/firmware/ap6181/device-bcm.mk) #$(call inherit-product-if-exists, hardware/broadcom/wlan/firmware/ap6210/device-bcm.mk) $(call inherit-product-if-exists, hardware/broadcom/wlan/firmware/ap6212/device-bcm.mk) #$(call inherit-product-if-exists, hardware/broadcom/wlan/firmware/ap6330/device-bcm.mk) #rtl8723bs bt fw and config #$(call inherit-product, hardware/realtek/bluetooth/rtl8723bs/firmware/rtlbtfw_cfg.mk) # camera config for camera detector #PRODUCT_COPY_FILES += \ # device/softwinner/astar-y3/hawkview/sensor_list_cfg.ini:system/etc/hawkview/sensor_list_cfg.ini #add gms features #PRODUCT_COPY_FILES += \ # frameworks/native/data/etc/android.hardware.faketouch.xml:system/etc/permissions/android.hardware.faketouch.xml \ # frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:system/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \ # frameworks/native/data/etc/android.hardware.usb.host.xml:system/etc/permissions/android.hardware.usb.host.xml # 3G Data Card Packages #PRODUCT_PACKAGES += \ # u3gmonitor \ # chat \ # rild \ # pppd # 3G Data Card Configuration Flie #PRODUCT_COPY_FILES += \ # device/softwinner/polaris-common/rild/ip-down:system/etc/ppp/ip-down \ # device/softwinner/polaris-common/rild/ip-up:system/etc/ppp/ip-up \ # device/softwinner/polaris-common/rild/3g_dongle.cfg:system/etc/3g_dongle.cfg \ # device/softwinner/polaris-common/rild/usb_modeswitch:system/bin/usb_modeswitch \ # device/softwinner/polaris-common/rild/call-pppd:system/xbin/call-pppd \ # device/softwinner/polaris-common/rild/usb_modeswitch.sh:system/xbin/usb_modeswitch.sh \ # device/softwinner/polaris-common/rild/apns-conf_sdk.xml:system/etc/apns-conf.xml \ # device/softwinner/polaris-common/rild/libsoftwinner-ril.so:system/lib/libsoftwinner-ril.so #PRODUCT_COPY_FILES += \ # device/softwinner/polaris-common/rild/init.3gdongle.rc:root/init.sunxi.3gdongle.rc # 3G Data Card usb modeswitch File #PRODUCT_COPY_FILES += \ # $(call find-copy-subdir-files,*,device/softwinner/polaris-common/rild/usb_modeswitch.d,system/etc/usb_modeswitch.d) PRODUCT_PROPERTY_OVERRIDES += \ ro.sw.embeded.telephony = false PRODUCT_PROPERTY_OVERRIDES += \ persist.sys.timezone=Asia/Shanghai \ persist.sys.language=zh \ persist.sys.country=CN PRODUCT_PACKAGES += Bluetooth #PRODUCT_PROPERTY_OVERRIDES += \ # ro.product.8723b_bt.used=true #GPS Feature #PRODUCT_PACKAGES += gps.polaris #BOARD_USES_GPS_TYPE := simulator #PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.location.xml:system/etc/permissions/android.hardware.location.xml # evb logger PRODUCT_COPY_FILES += \ device/softwinner/astar-y3/tools/logger.sh:system/bin/logger.sh PRODUCT_PROPERTY_OVERRIDES += \ persist.sys.usb.config=mass_storage,adb \ ro.adb.secure=0 ro.udisk.lable=Polaris \ ro.font.scale=1.0 \ ro.hwa.force=false \ rw.logger=0 \ ro.sys.bootfast=true \ debug.hwc.showfps=0 \ debug.hwui.render_dirty_regions=false #ro.sys.storage_type = emulated \ #for gms #PRODUCT_PROPERTY_OVERRIDES += \ # ro.sys.mutedrm=true \ # ro.adb.secure=1 PRODUCT_PROPERTY_OVERRIDES += \ ro.sf.lcd_density=213 \ ro.product.firmware=v2.0 $(call inherit-product-if-exists, device/softwinner/astar-y3/modules/modules.mk) DEVICE_PACKAGE_OVERLAYS := device/softwinner/astar-y3/overlay PRODUCT_CHARACTERISTICS := tablet # Overrides PRODUCT_AAPT_CONFIG := xlarge hdpi xhdpi large PRODUCT_AAPT_PREF_CONFIG := xhdpi PRODUCT_BRAND := Allwinner PRODUCT_NAME := astar_y3 PRODUCT_DEVICE := astar-y3 PRODUCT_MODEL := QUAD-CORE A33 y3 PRODUCT_MANUFACTURER := softwinner #include device/softwinner/polaris-common/prebuild/google/products/gms_base.mk 4、 R:\wyb\ap6212a0_a33_sc3817r\android\device\softwinner\astar-y3\BoardConfig.mk # wifi and bt configuration # 1. Wifi Configuration # 1.1 realtek wifi support # 1.1 realtek wifi configuration #BOARD_WIFI_VENDOR := realtek ifeq ($(BOARD_WIFI_VENDOR), realtek) WPA_SUPPLICANT_VERSION := VER_0_8_X BOARD_WPA_SUPPLICANT_DRIVER := NL80211 BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_rtl BOARD_HOSTAPD_DRIVER := NL80211 BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_rtl SW_BOARD_USR_WIFI := rtl8188eu BOARD_WLAN_DEVICE := rtl8188eu #SW_BOARD_USR_WIFI := rtl8723au #BOARD_WLAN_DEVICE := rtl8723au #SW_BOARD_USR_WIFI := rtl8723bs #BOARD_WLAN_DEVICE := rtl8723bs endif # 1.2 broadcom wifi support BOARD_WIFI_VENDOR := broadcom ifeq ($(BOARD_WIFI_VENDOR), broadcom) BOARD_WPA_SUPPLICANT_DRIVER := NL80211 WPA_SUPPLICANT_VERSION := VER_0_8_X BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_bcmdhd BOARD_HOSTAPD_DRIVER := NL80211 BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_bcmdhd BOARD_WLAN_DEVICE := bcmdhd WIFI_DRIVER_FW_PATH_PARAM := "/sys/module/bcmdhd/parameters/firmware_path" #SW_BOARD_USR_WIFI := AP6181 #SW_BOARD_USR_WIFI := AP6210 #WIFI_DRIVER_FW_PATH_STA := "/system/vendor/modules/fw_bcm40181a2.bin" #WIFI_DRIVER_FW_PATH_P2P := "/system/vendor/modules/fw_bcm40181a2_p2p.bin" #WIFI_DRIVER_FW_PATH_AP := "/system/vendor/modules/fw_bcm40181a2_apsta.bin" # 2017/6/21 15:11 wenyuanbo configure ap6212 use ap6210 SW_BOARD_USR_WIFI := AP6212 WIFI_DRIVER_FW_PATH_STA := "/system/vendor/modules/fw_bcm43438a0.bin" WIFI_DRIVER_FW_PATH_P2P := "/system/vendor/modules/fw_bcm43438a0_p2p.bin" WIFI_DRIVER_FW_PATH_AP := "/system/vendor/modules/fw_bcm43438a0_apsta.bin" #SW_BOARD_USR_WIFI := AP6330 #WIFI_DRIVER_FW_PATH_STA := "/system/vendor/modules/fw_bcm40183b2_ag.bin" #WIFI_DRIVER_FW_PATH_P2P := "/system/vendor/modules/fw_bcm40183b2_ag_p2p.bin" #WIFI_DRIVER_FW_PATH_AP := "/system/vendor/modules/fw_bcm40183b2_ag_apsta.bin" endif #1.3 eag wifi config #BOARD_WIFI_VENDOR := eagle ifeq ($(BOARD_WIFI_VENDOR), eagle) WPA_SUPPLICANT_VERSION := VER_0_8_X BOARD_WPA_SUPPLICANT_DRIVER := NL80211 BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_eagle BOARD_HOSTAPD_DRIVER := NL80211 BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_eagle SW_BOARD_USR_WIFI := esp8089 BOARD_WLAN_DEVICE := esp8089 endif # 2. Bluetooth Configuration # make sure BOARD_HAVE_BLUETOOTH is true for every bt vendor BOARD_HAVE_BLUETOOTH := true BOARD_HAVE_BLUETOOTH_BCM := true #SW_BOARD_HAVE_BLUETOOTH_NAME := ap6210 SW_BOARD_HAVE_BLUETOOTH_NAME := ap6212 #SW_BOARD_HAVE_BLUETOOTH_NAME := ap6330 #BOARD_HAVE_BLUETOOTH_RTK := true #BLUETOOTH_HCI_USE_RTK_H5 := true #SW_BOARD_HAVE_BLUETOOTH_NAME := rtl8723bs 5、 R:\wyb\ap6212a0_a33_sc3817r\android\device\softwinner\astar-y3\init.sun8i.rc on early-fs mount_all /fstab.sun8i setprop ro.crypto.fuse_sdcard true insmod /system/vendor/modules/disp.ko insmod /system/vendor/modules/lcd.ko insmod /system/vendor/modules/mali.ko insmod /system/vendor/modules/leds-sunxi.ko insmod /system/vendor/modules/bcmdhd.ko insmod /system/vendor/modules/bcm_btlpm.ko #2G or 3G init.rc # import init.sunxi.3gdongle.rc ## 1. realtek & eagle wifi service ## 1.1 realtek & eagle wifi sta service #service wpa_supplicant /system/bin/wpa_supplicant \ # -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ # -O/data/misc/wifi/sockets \ # -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0 # # we will start as root and wpa_supplicant will switch to user wifi # # after setting up the capabilities required for WEXT # # user wifi # # group wifi inet keystore # class main # socket wpa_wlan0 dgram 660 wifi wifi # disabled # oneshot # ## 1.2 realtek & eagle wifi sta p2p concurrent service #service p2p_supplicant /system/bin/wpa_supplicant \ # -ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf \ # -e/data/misc/wifi/entropy.bin -N \ # -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ # -O/data/misc/wifi/sockets \ # -g@android:wpa_wlan0 # class main # socket wpa_wlan0 dgram 660 wifi wifi # disabled # oneshot # 2. broadcom wifi service # 2.1 broadcom wifi station and softap service wpa_supplicant /system/bin/wpa_supplicant \ -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ -I/system/etc/wifi/wpa_supplicant_overlay.conf \ -O/data/misc/wifi/sockets \ -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0 # we will start as root and wpa_supplicant will switch to user wifi # after setting up the capabilities required for WEXT # user wifi # group wifi inet keystore class main socket wpa_wlan0 dgram 660 wifi wifi disabled oneshot # 2.2 broadcom wifi sta p2p concurrent service service p2p_supplicant /system/bin/wpa_supplicant \ -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ -I/system/etc/wifi/wpa_supplicant_overlay.conf \ -O/data/misc/wifi/sockets -N \ -ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf \ -I/system/etc/wifi/p2p_supplicant_overlay.conf \ -puse_p2p_group_interface=1 -e/data/misc/wifi/entropy.bin \ -g@android:wpa_wlan0 # we will start as root and wpa_supplicant will switch to user wifi # after setting up the capabilities required for WEXT # user wifi # group wifi inet keystore class main socket wpa_wlan0 dgram 660 wifi wifi disabled oneshot 6、(不需要修改) R:\wyb\ap6212a0_a33_sc3817r\android\device\softwinner\astar-y3\ueventd.sun8i.rc 7、 R:\wyb\ap6212a0_a33_sc3817r\android\frameworks\base\packages\SettingsProvider\res\values\defaults.xml 1800000 true 8、 R:\wyb\ap6212a0_a33_sc3817r\android\frameworks\base\services\java\com\android\server\BatteryService.java // private static final boolean DEBUG = false; private static final boolean DEBUG = true; private void sendIntentLocked() { // Pack up the values and broadcast them to everyone final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_REPLACE_PENDING); int icon = getIconLocked(mBatteryProps.batteryLevel); intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus); intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth); intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryProps.batteryPresent); //intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryProps.batteryLevel); intent.putExtra(BatteryManager.EXTRA_LEVEL, 100); intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE); intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon); intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType); //intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryProps.batteryVoltage); intent.putExtra(BatteryManager.EXTRA_VOLTAGE, 4200); intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryProps.batteryTemperature); intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryProps.batteryTechnology); intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger); if (DEBUG) { Slog.d(TAG, "2016/12/05 10:41 wenyuanbo **** Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel + ", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus + ", health:" + mBatteryProps.batteryHealth + ", present:" + mBatteryProps.batteryPresent + ", voltage: " + mBatteryProps.batteryVoltage + ", temperature: " + mBatteryProps.batteryTemperature + ", technology: " + mBatteryProps.batteryTechnology + ", AC powered:" + mBatteryProps.chargerAcOnline + ", USB powered:" + mBatteryProps.chargerUsbOnline + ", Wireless powered:" + mBatteryProps.chargerWirelessOnline + ", icon:" + icon + ", invalid charger:" + mInvalidCharger); } mHandler.post(new Runnable() { @Override public void run() { ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); } }); } 9、(直接拷贝同目录下的ap6210:) R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\libbt\conf\softwinner\ap6212\Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := bt_vendor.conf LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth LOCAL_MODULE_TAGS := eng LOCAL_SRC_FILES := $(LOCAL_MODULE) include $(BUILD_PREBUILT) R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\libbt\conf\softwinner\ap6212\bt_vendor.conf # UART device port where Bluetooth controller is attached UartPort = /dev/ttyS1 # Firmware patch file location FwPatchFilePath = /system/vendor/modules/ # Firmware Name FwPatchFileName = bcm43438a0.hcd 10、新增:vnd_astar-y3-ap6212.txt,直接拷贝:vnd_astar-y2-ap6210.txt R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\libbt\include\vnd_astar-y3-ap6212.txt R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\libbt\include\vnd_astar-y2-ap6210.txt BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyS1" FW_PATCHFILE_LOCATION = "/system/vendor/modules/" LPM_IDLE_TIMEOUT_MULTIPLE = 5 UART_TARGET_BAUD_RATE = 1500000 BT_WAKE_VIA_PROC = TRUE #LPM_SLEEP_MODE = FALSE BTVND_DBG = TRUE BTHW_DBG = TRUE VNDUSERIAL_DBG = TRUE UPIO_DBG = TRUE 11、 R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\libbt\src\userial_vendor.c //#ifdef USE_AP6210_BT_MODULE #if defined(USE_AP6210_BT_MODULE) || defined(USE_AP6212_BT_MODULE) /* PATCH for AP6210. Will detect CTS(module side) to select transport mode*/ ALOGE("userial vendor open: USE AP6210 BT MODULE."); usleep(100000); close(vnd_userial.fd); if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR)) == -1) { ALOGE("userial vendor open: unable to open %s", vnd_userial.port_name); return -1; } #endif //USE_AP6210_BT_MODULE 12、 R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\libbt\Android.mk ifeq ($(SW_BOARD_HAVE_BLUETOOTH_NAME), ap6210) LOCAL_CFLAGS += -DUSE_AP6210_BT_MODULE endif ifeq ($(SW_BOARD_HAVE_BLUETOOTH_NAME), ap6212) LOCAL_CFLAGS += -DUSE_AP6212_BT_MODULE endif ifeq ($(SW_BOARD_HAVE_BLUETOOTH_NAME), ap6330) include $(LOCAL_PATH)/conf/softwinner/ap6330/Android.mk endif ifeq ($(SW_BOARD_HAVE_BLUETOOTH_NAME), ap6210) include $(LOCAL_PATH)/conf/softwinner/ap6210/Android.mk endif ifeq ($(SW_BOARD_HAVE_BLUETOOTH_NAME), ap6212) include $(LOCAL_PATH)/conf/softwinner/ap6212/Android.mk endif 13、 R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\libbt\vnd_buildcfg.mk ifeq ($(SW_BOARD_HAVE_BLUETOOTH_NAME), ap6210) SRC := $(call my-dir)/include/$(addprefix vnd_, $(addsuffix -ap6210.txt,$(basename $(TARGET_DEVICE)))) endif ifeq ($(SW_BOARD_HAVE_BLUETOOTH_NAME), ap6212) SRC := $(call my-dir)/include/$(addprefix vnd_, $(addsuffix -ap6212.txt,$(basename $(TARGET_DEVICE)))) endif 14、(这些AP6212的WIFI的bin文件和BT的hcd文件来自全志R16的SDK,当然也可以找正基原厂/代理商索取:) R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\wlan\firmware\ap6212\bcm43438a0.hcd (根据ap6210修改:) R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\wlan\firmware\ap6212\device-bcm.mk # # Copyright (C) 2008 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ######################## -include hardware/broadcom/wlan/bcmdhd/config/config-bcm.mk PRODUCT_COPY_FILES += \ hardware/broadcom/wlan/firmware/ap6212/fw_bcm43438a0.bin:system/vendor/modules/fw_bcm43438a0.bin \ hardware/broadcom/wlan/firmware/ap6212/fw_bcm43438a0_apsta.bin:system/vendor/modules/fw_bcm43438a0_apsta.bin \ hardware/broadcom/wlan/firmware/ap6212/fw_bcm43438a0_p2p.bin:system/vendor/modules/fw_bcm43438a0_p2p.bin \ hardware/broadcom/wlan/firmware/ap6212/nvram_ap6212.txt:system/vendor/modules/nvram_ap6212.txt \ hardware/broadcom/wlan/firmware/ap6212/bcm43438a0.hcd:system/vendor/modules/bcm43438a0.hcd #hardware/broadcom/wlan/firmware/ap6212/config.txt:system/vendor/modules/config.txt ######################## R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\wlan\firmware\ap6212\fw_bcm43438a0.bin R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\wlan\firmware\ap6212\fw_bcm43438a0_apsta.bin R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\wlan\firmware\ap6212\fw_bcm43438a0_p2p.bin R:\wyb\ap6212a0_a33_sc3817r\android\hardware\broadcom\wlan\firmware\ap6212\nvram_ap6212.txt 15、(可选修改:) R:\wyb\ap6212a0_a33_sc3817r\android\packages\apps\Camera2\src\com\android\camera\CameraActivity.java private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { int Level = intent.getIntExtra("level", 0); int Scale = intent.getIntExtra("scale", 100); Log.w(TAG, "2016/11/29 19:54 &&&& wenyuanbo battery Level" + Level); /* *Logic: *1.the battery level is lower then 5%. *2.if in camera, make sure that not in the snapshot progress. *3.if in videocamera, make sure that not in the videorecording progress. *4.everytime starting the camera activity, the battery level is broadcasted, * if meeting the conditions above, give a dialog, press it and finish the activity. *5.if the conditions are not satisfied when started, play for a moment, in the camera acitvity * or video camera activity, the conditiosn are satisfied, also give a dialog for finishing the activity. * *by fuqiang. */ if(Level < 5) { Runnable runnable_close_camera = new Runnable() { @Override public void run() { //close the camera. // CameraActivity.this.finish(); } }; Log.w(TAG, "2016/11/29 18:20 **** wenyuanbo battery Level" + Level); showLocationDialog(); } /* *Logic: *1.the battery level is lhigher then 5% and lower than 15%. *2.if in camera, make sure that not in the snapshot progress. *3.if in videocamera, make sure that not in the videorecording progress. *4.whether in camera or in videocamera, make sure that the flash mode is supported. *5.everytime starting the camera activity, the battery level is broadcasted, * if meeting the conditions above, forbidden the flash(gray icon), give a dialog to notise user. *6.if the conditions are not satisfied when started, play for a moment, in the camera acitvity * or video camera activity, the conditiosn are satisfied, forbidden the flash and give a notice dialog. *7.the dialog is only given once for each camera activity starting. * *by fuqiang. */ else if(Level < 16) { //close the flash mode. /* if (mIsLowBatteryDialogShown == false) { mRotateDialog.showAlertDialog( getString(R.string.warning), getString(R.string.low_battery_15), null, null, getString(R.string.close), null); mIsLowBatteryDialogShown = true; } */ } } } }; 16、(可选:) R:\wyb\ap6212a0_a33_sc3817r\lichee\tools\pack\chips\sun8iw5p1\configs\default\env.cfg bootdelay=3 loglevel=8 17、 R:\wyb\ap6212a0_a33_sc3817r\lichee\tools\pack\chips\sun8iw5p1\configs\y3\sys_config.fex [power_sply] dcdc1_vol = 3000 dcdc2_vol = 1100 dcdc3_vol = 1200 dcdc4_vol = 0 dcdc5_vol = 1500 aldo1_vol = 3300 aldo2_vol = 2500 aldo3_vol = 3000 dldo1_vol = 3300 dldo2_vol = 3300 dldo3_vol = 2800 ;gpio0_vol = 2800 ldoio0_vol = 2800 ;---------------------------------------------------------------------------------- ;uart configuration ;uart_used = uart x enable ;uart_type = 2:2 wire,4:4 wire,8:8 wire, full function ;---------------------------------------------------------------------------------- [uart0] uart_used = 1 uart_port = 0 uart_type = 2 uart_tx = port:PF02 uart_rx = port:PF04 [uart1] uart_used = 1 uart_port = 1 uart_type = 4 uart_tx = port:PG06 uart_rx = port:PG07 uart_rts = port:PG08 uart_cts = port:PG09 [uart2] uart_used = 1 uart_type = 4 uart_tx = port:PB00 uart_rx = port:PB01 uart_rts = port:PB02 uart_cts = port:PB03 [uart3] uart_used = 0 uart_type = 4 uart_tx = port:PH06 uart_rx = port:PH07 uart_rts = port:PH08 uart_cts = port:PH09 [uart4] uart_used = 0 uart_port = 4 uart_type = 2 uart_tx = port:PA04 uart_rx = port:PA05 uart_rts = port:PA06 uart_cts = port:PA07 ;---------------------------------------------------------------------------------- ;capacitor tp configuration ;ctp_twi_id : twi controller ID ;ctp_twi_addr : I2C slave address, 7bit ;ctp_screen_max_x/_y : resolution of touch panel ;ctp_revert_x/_y_flag : whether need to revert x/y ;ctp_exchange_x_y_flag: whether need to exchange the value of x and y ;ctp_int_port : port for tp's interrupt signal ;ctp_wakeup : port for wakeup tp ;---------------------------------------------------------------------------------- [ctp_para] ctp_used = 1 ctp_name = "gt82x" ctp_twi_id = 0 ctp_twi_addr = 0x5d ctp_screen_max_x = 1280 ctp_screen_max_y = 800 ctp_revert_x_flag = 1 ctp_revert_y_flag = 1 ctp_exchange_x_y_flag = 1 ctp_int_port = port:PL04 ctp_wakeup = port:PL03 ctp_power_ldo = ctp_power_ldo_vol = ctp_power_io = ;-------------------------------------------------------------------------------- ; CTP automatic detection configuration ;ctp_detect_used --- Whether startup automatic inspection function. 1:used,0:unused ;Module name postposition 1 said detection, 0 means no detection. ;-------------------------------------------------------------------------------- [ctp_list_para] ctp_det_used = 1 ft5x_ts = 1 gt82x = 1 gslX680 = 1 gslX680new = 0 gt9xx_ts = 1 gt9xxf_ts = 0 tu_ts = 0 gt818_ts = 1 zet622x = 1 aw5306_ts = 1 icn83xx_ts = 0 [lcd0_para] lcd_used = 1 lcd_driver_name = "default_lcd" lcd_if = 3 lcd_x = 1280 lcd_y = 800 lcd_width = 150 lcd_height = 94 lcd_dclk_freq = 71 lcd_pwm_used = 1 lcd_pwm_ch = 0 lcd_pwm_freq = 50000 lcd_pwm_pol = 1 lcd_hbp = 20 lcd_ht = 1418 lcd_hspw = 10 lcd_vbp = 10 lcd_vt = 830 lcd_vspw = 5 lcd_lvds_if = 0 lcd_lvds_colordepth = 1 lcd_lvds_mode = 0 lcd_frm = 1 lcd_gamma_en = 0 lcd_bright_curve_en = 0 lcd_cmap_en = 0 deu_mode = 0 lcdgamma4iep = 22 smart_color = 90 lcd_bl_en = port:PD13 ;ap6xxx_wl_regon = port:PL06 ;lcd_bl_en = port:PL06 lcd_power = "axp22_dc1sw" lcdd0 = port:PD18 lcdd1 = port:PD19 lcdd2 = port:PD20 lcdd3 = port:PD21 lcdd4 = port:PD22 lcdd5 = port:PD23 lcdd6 = port:PD24 lcdd7 = port:PD25 lcdd8 = port:PD26 lcdd9 = port:PD27 ;---------------------------------------------------------------------------------- ;pwm config ;---------------------------------------------------------------------------------- [pwm0_para] pwm_used = 0 pwm_positive = port:PH00 [pwm1_para] pwm_used = 1 pwm_positive = port:PH01 ;-------------------------------------------------------------------------------- ;wifi configuration ;wifi_sdc_id: 0- SDC0, 1- SDC1, 2- SDC2, 3- SDC3 ;wifi_usbc_id: 0- USB0, 1- USB1, 2- USB2 ;wifi_usbc_type: 1- EHCI(speed 2.0), 2- OHCI(speed 1.0) ;wifi_mod_sel: 0- none, 1- ap6181, 2- ap6210(wifi+bt), ; 3 - rtl8188eu, 4- rtl8723au(wifi+bt), ; 5 - rtl8723bs, 6- esp8089 ;-------------------------------------------------------------------------------- [wifi_para] wifi_used = 1 wifi_sdc_id = 1 wifi_usbc_id = 1 wifi_usbc_type = 1 wifi_mod_sel = 2 wifi_power = "axp22_dldo1" wifi_power_ext1 = "axp22_dldo2" wifi_power_ext2 = "axp22_aldo1" wifi_power_switch = ;wifi_power_switch = port:power0 ; 1 - ap6181 sdio wifi gpio config ;ap6xxx_wl_regon = port:PL06 ;ap6xxx_wl_host_wake = port:PL07 ;ap6xxx_lpo_use_apclk = 1 ; 2 - ap6210 sdio wifi gpio config ap6xxx_wl_regon = port:PL06 ;ap6xxx_wl_regon = port:PD13 ap6xxx_wl_host_wake = port:PL07 ap6xxx_bt_regon = port:PL08 ap6xxx_bt_wake = port:PL10 ap6xxx_bt_host_wake = port:PL09 ap6xxx_lpo_use_apclk = 1 ; 3 - rtl8188eu usb wifi gpio conifg ; 4 - rtl8723au usb wifi + bt ; 5 - rtl8723bs sdio wifi + bt ;rtl8723bs_chip_en = port:PL11 ;rtl8723bs_wl_regon = port:PL06 ;rtl8723bs_wl_host_wake = port:PL07 ;rtl8723bs_bt_regon = port:PL08 ;rtl8723bs_bt_wake = port:PL10 ;rtl8723bs_bt_host_wake = port:PL09 ;rtl8723bs_lpo_use_apclk = 0 ; 6 - eagle sdio wifi ;esp_wl_chip_en = port:PL03 ;esp_wl_rst = port:PL02 ;-------------------------------------------------------------------------------- ;blue tooth ;bt_used ---- blue tooth used (0- no used, 1- used) ;bt_uard_id ---- uart index ;-------------------------------------------------------------------------------- [bt_para] bt_used = 1 bt_uart_id = 1 power_start = 3 pmu_temp_enable = 0 18、 刷机之后,BT可以用。 传输4.5MB的JPG图片大概需要2分钟。 WIFI: 在设置→WLAN(打开之后): shell@astar-y3:/ $ shell@astar-y3:/ $ [ 469.609956] init: computing context for service '/system/bin/wpa_supplicant' [ 469.618386] init: starting 'p2p_supplicant' [ 469.625739] init: Created socket '/dev/socket/wpa_wlan0' with mode '660', user '1010', group '1010' [ 469.673379] init: waitpid returned pid 2065, status = 0000ff00 [ 469.679923] init: process 'p2p_supplicant', pid 2065 exited [ 476.197334] sndpcm_unmute,line:1099 [ 451.464755] CPU1: Booted secondary processor [ 478.459403] CPU1: shutdown [ 478.462947] [hotplug]: cpu(0) try to kill cpu(1) [ 478.468478] [hotplug]: cpu1 is killed! . shell@astar-y3:/ $ 分析启动的log: [ 17.526849] gpio ap6xxx_wl_regon set val 1, act val 1 [ 17.632508] [ap6xxx]: sdio wifi power state: on [ 17.637576] [mmc]: sdc1 set ios: clk 0Hz bm PP pm UP vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 17.637751] =========== WLAN placed in POWER ON ======== [ 17.654651] [mmc]: sdc1 card_power_on start... [ 17.659576] [mmc]: sdc1 power_supply is null [ 17.664322] [mmc]: sdc1 card_power_on ok [ 17.680039] [mmc]: sdc1 set ios: clk 400000Hz bm PP pm ON vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 17.690275] [mmc]: mclk 0xf1c2008c 0x8002000e [ 17.772361] [mmc]: *** sunxi_mci_dump_errinfo(L773): smc 1 err, cmd 52, RTO !! [ 17.781309] [mmc]: *** sunxi_mci_dump_errinfo(L773): smc 1 err, cmd 52, RTO !! [ 17.789448] [mmc]: sdc1 set ios: clk 400000Hz bm PP pm ON vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 17.799714] [mmc]: mclk 0xf1c2008c 0x8002000e [ 17.862032] [mmc]: sdc1 set ios: clk 400000Hz bm PP pm ON vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 17.872262] [mmc]: mclk 0xf1c2008c 0x8002000e [ 17.933953] [mmc]: *** sunxi_mci_dump_errinfo(L773): smc 1 err, cmd 8, RTO !! [ 17.941997] *******************Try sdio******************* [ 17.948400] [mmc]: sdc1 set ios: clk 400000Hz bm PP pm ON vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 17.958630] [mmc]: mclk 0xf1c2008c 0x8002000e [ 18.027775] mmc1: queuing unknown CIS tuple 0x80 (2 bytes) [ 18.035416] mmc1: queuing unknown CIS tuple 0x80 (3 bytes) [ 18.043087] mmc1: queuing unknown CIS tuple 0x80 (3 bytes) [ 18.051920] mmc1: queuing unknown CIS tuple 0x80 (7 bytes) [ 18.145287] [mmc]: sdc1 set ios: clk 400000Hz bm PP pm ON vdd 3.3V width 1 timing SD-HS(SDR25) dt B [ 18.155436] [mmc]: mclk 0xf1c2008c 0x8002000e [ 18.215346] [mmc]: sdc1 set ios: clk 50000000Hz bm PP pm ON vdd 3.3V width 1 timing SD-HS(SDR25) dt B [ 18.225736] [mmc]: mclk 0xf1c2008c 0x8100000b [ 18.285675] [mmc]: sdc1 set ios: clk 50000000Hz bm PP pm ON vdd 3.3V width 4 timing SD-HS(SDR25) dt B [ 18.296021] [mmc]: mclk 0xf1c2008c 0x8140030b [ 18.357915] mmc1: new high speed SDIO card at address 0001 [ 18.364532] bcmsdh_register: Linux Kernel SDIO/MMC Driver [ 18.364575] *******************sdio init ok******************* [ 18.377207] bcm_wlan_get_oob_irq enter. [ 18.381537] gpio [359] map to virq [7] ok [ 18.388851] F1 signature OK, socitype:0x1 chip:0xa9a6 rev:0x0 pkg:0x4 [ 18.396019] dhdsdio_probe_attach: unsupported chip: 0xa9a6 [ 18.402155] dhdsdio_probe: dhdsdio_probe_attach failed [ 18.407899] bcmsdh_probe: device attach failed [ 18.412981] [ 18.412984] Dongle Host Driver, version 1.88.45.3 (r420671) [ 18.412989] Compiled in drivers/net/wireless/bcmdhd on Jun 26 2017 at 12:06:39 [ 18.428835] dhd_module_init: sdio_register_driver timeout or error [ 18.435928] gpio ap6xxx_wl_regon set val 0, act val 0 [ 18.541549] [ap6xxx]: sdio wifi power state: off [ 18.546679] =========== WLAN placed in POWER OFF ======== [ 18.546915] mmc1: card 0001 removed [ 18.546995] [mmc]: mmc not poweroff notifiy [ 18.547007] [mmc]: sdc1 set ios: clk 0Hz bm OD pm OFF vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 18.547160] [mmc]: sdc1 card_power_off start... [ 18.547166] [mmc]: sdc1 power_supply is null [ 18.547173] [mmc]: sdc1 card_power_off ok [ 18.631655] init: command 'insmod' r=-1 [ 18.636066] init: command 'insmod' r=-1 [ 18.658010] fs_mgr: swapon failed for /dev/block/zram0 [ 18.663804] init: command 'swapon_all' r=-1 [ 18.668504] init: processing action 0x58e70 (console_init) [ 18.675396] init: width = 1280 [ 18.678788] init: height = 800 [ 18.682224] init: s.st_size = 3145728 [ 18.686308] init: logo match failed!fbsize = 4096000 [ 18.718811] init: command 'console_init' r=0 [ 18.723628] init: processing action 0x55bf0 (fs) [ 18.730640] init: command 'mkdir' r=-2 [ 18.741901] init: command 'insmod' r=0 [ 18.752227] init: command 'insmod' r=0 [ 18.756491] init: command 'insmod' r=-1 [ 18.771211] init: command 'insmod' r=0 [ 18.779731] init: command 'insmod' r=0 [ 18.791739] init: command 'insmod' r=0 [ 18.803941] init: command 'insmod' r=0 [ 18.816178] init: command 'insmod' r=0 19、查找:(dhdsdio_probe_attach: unsupported chip: 0xa9a6) rootroot@rootroot-E400:~$ cd wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd/ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ grep "unsupported chip" . -R ./dhd_sdio.c: DHD_ERROR(("%s: unsupported chip: 0xx\n", ./sbutils.c: SI_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", 匹配到二进制文件 ./dhd_sdio.o 匹配到二进制文件 ./bcmdhd.o 匹配到二进制文件 ./bcmdhd.ko 匹配到二进制文件 ./sbutils.o rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ 经过确认: R:\wyb\ap6212a0_a33_sc3817r\lichee\linux-3.4\drivers\net\wireless\bcmdhd\dhd_sdio.c static bool dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, uint16 devid) { …… bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev); if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) { DHD_ERROR(("%s: unsupported chip: 0xx\n", __FUNCTION__, bus->sih->chip)); goto fail; } …… } 继续追踪: static bool dhdsdio_chipmatch(uint16 chipid) { if (chipid == BCM4325_CHIP_ID) return TRUE; if (chipid == BCM4329_CHIP_ID) return TRUE; if (chipid == BCM4315_CHIP_ID) return TRUE; if (chipid == BCM4319_CHIP_ID) return TRUE; if (chipid == BCM4336_CHIP_ID) return TRUE; if (chipid == BCM4330_CHIP_ID) return TRUE; if (chipid == BCM43237_CHIP_ID) return TRUE; if (chipid == BCM43362_CHIP_ID) return TRUE; if (chipid == BCM4314_CHIP_ID) return TRUE; if (chipid == BCM43242_CHIP_ID) return TRUE; if (chipid == BCM43340_CHIP_ID) return TRUE; if (chipid == BCM43341_CHIP_ID) return TRUE; if (chipid == BCM43143_CHIP_ID) return TRUE; if (chipid == BCM43342_CHIP_ID) return TRUE; if (chipid == BCM4334_CHIP_ID) return TRUE; if (chipid == BCM43239_CHIP_ID) return TRUE; if (chipid == BCM4324_CHIP_ID) return TRUE; if (chipid == BCM4335_CHIP_ID) return TRUE; if (chipid == BCM4339_CHIP_ID) return TRUE; if (chipid == BCM43349_CHIP_ID) return TRUE; if (chipid == BCM4345_CHIP_ID) return TRUE; if (chipid == BCM4350_CHIP_ID) return TRUE; if (chipid == BCM4354_CHIP_ID) return TRUE; if (chipid == BCM4356_CHIP_ID) return TRUE; if (chipid == BCM4358_CHIP_ID) return TRUE; if (chipid == BCM4371_CHIP_ID) return TRUE; if (chipid == BCM43430_CHIP_ID) return TRUE; if (BCM4349_CHIP(chipid)) return TRUE; return FALSE; } 20、 rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ ll 总用量 40 drwxr-xr-x 7 rootroot rootroot 4096 6月 26 12:02 ./ drwx------ 6 rootroot rootroot 4096 6月 26 14:16 ../ drwxr-xr-x 10 rootroot rootroot 4096 9月 4 2014 brandy/ -rw-rw-r-- 1 rootroot rootroot 116 6月 26 12:02 .buildconfig drwxr-xr-x 15 rootroot rootroot 4096 9月 4 2014 buildroot/ -r-xr-xr-x 1 rootroot rootroot 55 9月 4 2014 build.sh* drwxr-xr-x 28 rootroot rootroot 4096 6月 26 14:30 linux-3.4/ drwxrwxr-x 3 rootroot rootroot 4096 6月 26 12:02 out/ -r--r--r-- 1 rootroot rootroot 232 9月 4 2014 README drwxr-xr-x 7 rootroot rootroot 4096 6月 7 19:33 tools/ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ ./build.sh config Welcome to mkscript setup progress All available chips: 0. sun8iw5p1 Choice: 0 All available platforms: 0. android 1. dragonboard 2. linux Choice: 0 All available kernel: 0. linux-3.4 Choice: 0 All available boards: 0. evb 1. maple 2. redwood 3. y2 4. y3 Choice: 4 rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ ./build.sh INFO: ---------------------------------------- INFO: build lichee ... INFO: chip: sun8iw5p1 INFO: platform: android INFO: kernel: linux-3.4 INFO: board: y3 INFO: output: out/sun8iw5p1/android/y3 INFO: ---------------------------------------- INFO: build buildroot ... external toolchain has been installed INFO: build buildroot OK. INFO: build kernel ... INFO: prepare toolchain ... Building kernel CHK include/linux/version.h CHK include/generated/utsrelease.h make[1]: “include/generated/mach-types.h”是最新的。 CALL scripts/checksyscalls.sh CHK include/generated/compile.h CC arch/arm/mach-sunxi/pm/standby/common.o CC arch/arm/mach-sunxi/pm/standby/standby_clock.o CC arch/arm/mach-sunxi/pm/standby/standby_ir.o CC arch/arm/mach-sunxi/pm/standby/standby_key.o CC arch/arm/mach-sunxi/pm/standby/standby_power.o CC arch/arm/mach-sunxi/pm/standby/standby_twi.o CC arch/arm/mach-sunxi/pm/standby/standby_usb.o AS arch/arm/mach-sunxi/pm/standby/standby_delay.o CC arch/arm/mach-sunxi/pm/standby/./arisc/standby_arisc.o CC arch/arm/mach-sunxi/pm/standby/./arisc/arisc_hwmsgbox.o CHK kernel/config_data.h CC arch/arm/mach-sunxi/pm/standby/./arisc/arisc_hwspinlock.o CC arch/arm/mach-sunxi/pm/standby/./arisc/arisc_message_manager.o CC arch/arm/mach-sunxi/pm/standby/./../pm_debug.o CC arch/arm/mach-sunxi/pm/standby/./../mem_timing.o CC arch/arm/mach-sunxi/pm/standby/./../mem_mmu_pc.o AS arch/arm/mach-sunxi/pm/standby/./../mem_mmu_pc_asm.o CC arch/arm/mach-sunxi/pm/standby/./../mem_serial.o CC arch/arm/mach-sunxi/pm/standby/./../mem_printk.o AS arch/arm/mach-sunxi/pm/standby/./../mem_divlib.o CC arch/arm/mach-sunxi/pm/standby/./../mem_divlibc.o CC arch/arm/mach-sunxi/pm/standby/./../mem_int.o CC arch/arm/mach-sunxi/pm/standby/./../mem_tmr.o CC arch/arm/mach-sunxi/pm/standby/./../mem_tmstmp.o CC arch/arm/mach-sunxi/pm/standby/./../mem_clk.o CC arch/arm/mach-sunxi/pm/standby/./../mem_hwspinlock.o CC arch/arm/mach-sunxi/pm/standby/standby.o rm -rf *.o arch/arm/mach-sunxi/pm/standby/../*.o CC arch/arm/mach-sunxi/pm/standby/super/common.o CC arch/arm/mach-sunxi/pm/standby/super/super_twi.o CC [M] drivers/net/wireless/bcmdhd/dhd_sdio.o AS arch/arm/mach-sunxi/pm/standby/super/super_delay.o CC arch/arm/mach-sunxi/pm/standby/super/super_clock.o CC arch/arm/mach-sunxi/pm/standby/super/super_power.o CC arch/arm/mach-sunxi/pm/standby/super/super_cpus.o AS arch/arm/mach-sunxi/pm/standby/super/resume/resume1.o CC arch/arm/mach-sunxi/pm/standby/super/resume/resume_head.o CC arch/arm/mach-sunxi/pm/standby/super/resume/resume1_c_part.o CC arch/arm/mach-sunxi/pm/standby/../pm_debug.o CC arch/arm/mach-sunxi/pm/standby/../mem_timing.o CC arch/arm/mach-sunxi/pm/standby/../mem_mmu_pc.o AS arch/arm/mach-sunxi/pm/standby/../mem_mmu_pc_asm.o CC arch/arm/mach-sunxi/pm/standby/../mem_cpu.o CC arch/arm/mach-sunxi/pm/standby/../mem_serial.o CC arch/arm/mach-sunxi/pm/standby/../mem_printk.o CC [M] drivers/net/wireless/bcmdhd/dhd_cdc.o CC [M] drivers/net/wireless/bcmdhd/bcmsdh_linux.o CC [M] drivers/net/wireless/bcmdhd/dhd_common.o AS arch/arm/mach-sunxi/pm/standby/../mem_divlib.o CC arch/arm/mach-sunxi/pm/standby/../mem_divlibc.o drivers/net/wireless/bcmdhd/dhd_sdio.c: In function ‘dhdsdio_chipmatch’: drivers/net/wireless/bcmdhd/dhd_sdio.c:6936:16: error: ‘BCM43430_CHIP_ID’ undeclared (first use in this function) drivers/net/wireless/bcmdhd/dhd_sdio.c:6936:16: note: each undeclared identifier is reported only once for each function it appears in CC arch/arm/mach-sunxi/pm/standby/../mem_int.o make[4]: *** [drivers/net/wireless/bcmdhd/dhd_sdio.o] 错误 1 make[4]: *** 正在等待未完成的任务.... CC arch/arm/mach-sunxi/pm/standby/../mem_tmr.o CC arch/arm/mach-sunxi/pm/standby/../mem_tmstmp.o CC arch/arm/mach-sunxi/pm/standby/../mem_hwspinlock.o CC arch/arm/mach-sunxi/pm/standby/../mem_clk.o Source file is open Destination file is created. Source file is open Destination file is open. temp value is 400. 0 soure_file size is 9496. destination_file size is 0x2800. check sum generated is 0x68D92007. Everything is ok. rm -rf *.o arch/arm/mach-sunxi/pm/standby/../*.o CC arch/arm/mach-sunxi/pm/mem_mapping.o CC arch/arm/mach-sunxi/pm/mem_divlibc.o CC arch/arm/mach-sunxi/pm/mem_cpu.o AS arch/arm/mach-sunxi/pm/mem_cpu_asm.o AS arch/arm/mach-sunxi/pm/mem_mmu_pc_asm.o CC arch/arm/mach-sunxi/pm/mem_mmu_pc.o CC arch/arm/mach-sunxi/pm/mem_int.o CC arch/arm/mach-sunxi/pm/mem_clk.o CC arch/arm/mach-sunxi/pm/mem_tmr.o CC arch/arm/mach-sunxi/pm/mem_tmstmp.o CC arch/arm/mach-sunxi/pm/mem_twi.o CC arch/arm/mach-sunxi/pm/mem_gpio.o CC arch/arm/mach-sunxi/pm/mem_sram.o CC arch/arm/mach-sunxi/pm/mem_ccu.o CC arch/arm/mach-sunxi/pm/mem_cci400.o CC arch/arm/mach-sunxi/pm/mem_gtbus.o CC arch/arm/mach-sunxi/pm/pm_debug.o CC arch/arm/mach-sunxi/pm/mem_timing.o CC arch/arm/mach-sunxi/pm/mem_hwspinlock.o CC arch/arm/mach-sunxi/pm/pm.o CC arch/arm/mach-sunxi/pm/extended_standby.o CC arch/arm/mach-sunxi/pm/standby/super/super_power.o CC arch/arm/mach-sunxi/pm/standby/super/super_twi.o CC arch/arm/mach-sunxi/pm/standby/super/super_clock.o AS arch/arm/mach-sunxi/pm/standby.o AS arch/arm/mach-sunxi/pm/mem.o LD arch/arm/mach-sunxi/pm/pm_tmp.o LD arch/arm/mach-sunxi/pm/built-in.o LD arch/arm/mach-sunxi/built-in.o make[3]: *** [drivers/net/wireless/bcmdhd] 错误 2 make[2]: *** [drivers/net/wireless] 错误 2 make[1]: *** [drivers/net] 错误 2 make: *** [drivers] 错误 2 ERROR: build kernel Failed rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ 21、(dhdsdio_probe_attach: unsupported chip: 0xa9a6) R:\wyb\ap6212a0_a33_sc3817r\lichee\linux-3.4\drivers\net\wireless\bcmdhd\include\bcmdevs.h #define BCM4350_CHIP_ID 0x4350 #define BCM43430_CHIP_ID 43430 /* 43430 chipcommon chipid 0xa9a6 */ #define BCM4342_CHIP_ID 4342 可以编译通过了。 (查看属性:) shell@astar-y3:/ $ shell@astar-y3:/ $ cd /system/vendor/modules/ shell@astar-y3:/system/vendor/modules $ ll bcm* -rw-r--r-- root root 26020 2017-06-26 12:46 bcm43438a0.hcd -rw-r--r-- root root 748856 2017-06-26 12:46 bcmdhd.ko shell@astar-y3:/system/vendor/modules $ Microsoft Windows [版本 6.1.7600] 版权所有 (c) 2009 Microsoft Corporation。保留所有权利。 C:\Users\Administrator>cd R:\wyb\ap6212a0_a33_sc3817r\lichee\linux-3.4\drivers\n et\wireless\bcmdhd C:\Users\Administrator>r: R:\wyb\ap6212a0_a33_sc3817r\lichee\linux-3.4\drivers\net\wireless\bcmdhd>adb remount * daemon not running. starting it now on port 5037 * * daemon started successfully * remount succeeded R:\wyb\ap6212a0_a33_sc3817r\lichee\linux-3.4\drivers\net\wireless\bcmdhd> R:\wyb\ap6212a0_a33_sc3817r\lichee\linux-3.4\drivers\net\wireless\bcmdhd>adb push bcmdhd.ko /system/vendor/modules/ 1677 KB/s (748864 bytes in 0.436s) R:\wyb\ap6212a0_a33_sc3817r\lichee\linux-3.4\drivers\net\wireless\bcmdhd> 继续查看属性: shell@astar-y3:/system/vendor/modules $ ll bcm* -rw-r--r-- root root 26020 2017-06-26 12:46 bcm43438a0.hcd -rw-rw-rw- root root 748864 2017-06-26 14:34 bcmdhd.ko shell@astar-y3:/system/vendor/modules $ shell@astar-y3:/system/vendor/modules $ shell@astar-y3:/system/vendor/modules $ chmod 644 bcmdhd.ko Unable to chmod bcmdhd.ko: Operation not permitted 10|shell@astar-y3:/system/vendor/modules $ (必须在su下才能够修改属性:) shell@astar-y3:/system/vendor/modules $ su shell@astar-y3:/system/vendor/modules # chmod 644 bcmdhd.ko shell@astar-y3:/system/vendor/modules # shell@astar-y3:/system/vendor/modules # sync shell@astar-y3:/system/vendor/modules # reboot 22、 [ 0.658241] [wifi]: select wifi: ap6210 !! [ 0.658587] [ap6xxx]: module power name axp22_dldo1 [ 0.658601] [ap6xxx]: module power ext1 name axp22_dldo2 [ 0.658613] [ap6xxx]: module power ext2 name axp22_aldo1 [ 0.658721] [ap6xxx]: get ap6xxx wifi_power_switch failed [ 0.658731] [ap6xxx]: ap6xxx module power set by axp. [ 0.658930] [ap6xxx]: first time [ 0.659285] [ap6xxx]: regulator on. [ 0.661306] [wifi_pm]: wifi gpio init is OK !! (重启之后,WIFI模块要想办法配置为ap6212,现阶段借用的是AP6210!) [ 8.517657] gpio ap6xxx_wl_regon set val 1, act val 1 [ 8.623325] [ap6xxx]: sdio wifi power state: on [ 8.628389] [mmc]: sdc1 set ios: clk 0Hz bm PP pm UP vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 8.628566] =========== WLAN placed in POWER ON ======== [ 8.645459] [mmc]: sdc1 card_power_on start... [ 8.650397] [mmc]: sdc1 power_supply is null [ 8.655129] [mmc]: sdc1 card_power_on ok [ 8.680031] [mmc]: sdc1 set ios: clk 400000Hz bm PP pm ON vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 8.690267] [mmc]: mclk 0xf1c2008c 0x8002000e [ 8.772360] [mmc]: *** sunxi_mci_dump_errinfo(L773): smc 1 err, cmd 52, RTO !! [ 8.781316] [mmc]: *** sunxi_mci_dump_errinfo(L773): smc 1 err, cmd 52, RTO !! [ 8.789448] [mmc]: sdc1 set ios: clk 400000Hz bm PP pm ON vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 8.799684] [mmc]: mclk 0xf1c2008c 0x8002000e [ 8.861971] [mmc]: sdc1 set ios: clk 400000Hz bm PP pm ON vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 8.872189] [mmc]: mclk 0xf1c2008c 0x8002000e [ 8.933887] [mmc]: *** sunxi_mci_dump_errinfo(L773): smc 1 err, cmd 8, RTO !! [ 8.941921] *******************Try sdio******************* [ 8.948329] [mmc]: sdc1 set ios: clk 400000Hz bm PP pm ON vdd 3.3V width 1 timing LEGACY(SDR12) dt B [ 8.958545] [mmc]: mclk 0xf1c2008c 0x8002000e [ 9.027690] mmc1: queuing unknown CIS tuple 0x80 (2 bytes) [ 9.035325] mmc1: queuing unknown CIS tuple 0x80 (3 bytes) [ 9.043192] mmc1: queuing unknown CIS tuple 0x80 (3 bytes) [ 9.052046] mmc1: queuing unknown CIS tuple 0x80 (7 bytes) [ 9.145358] [mmc]: sdc1 set ios: clk 400000Hz bm PP pm ON vdd 3.3V width 1 timing SD-HS(SDR25) dt B [ 9.155486] [mmc]: mclk 0xf1c2008c 0x8002000e [ 9.215398] [mmc]: sdc1 set ios: clk 50000000Hz bm PP pm ON vdd 3.3V width 1 timing SD-HS(SDR25) dt B [ 9.225785] [mmc]: mclk 0xf1c2008c 0x8100000b [ 9.285721] [mmc]: sdc1 set ios: clk 50000000Hz bm PP pm ON vdd 3.3V width 4 timing SD-HS(SDR25) dt B [ 9.296049] [mmc]: mclk 0xf1c2008c 0x8140030b [ 9.357922] mmc1: new high speed SDIO card at address 0001 [ 9.364523] bcmsdh_register: Linux Kernel SDIO/MMC Driver [ 9.364563] *******************sdio init ok******************* [ 9.377203] bcm_wlan_get_oob_irq enter. [ 9.381534] gpio [359] map to virq [7] ok [ 9.388816] F1 signature OK, socitype:0x1 chip:0xa9a6 rev:0x0 pkg:0x4 [ 9.396740] DHD: dongle ram size is set to 524288(orig 524288) at 0x0 [ 9.404660] dhdsdio_probe: Disable prop_txstatus [ 9.410903] wl_create_event_handler(): thread:wl_event_handler:5d started [ 9.410914] tsk Enter, tsk = 0xddca13d8 [ 9.423788] p2p0: P2P Interface Registered [ 9.428464] dhd_attach(): thread:dhd_watchdog_thread:5e started [ 9.435144] dhd_attach(): thread:dhd_dpc:5f started [ 9.440653] dhd_attach(): thread:dhd_sysioc:60 started [ 9.447276] Broadcom Dongle Host Driver: register interface [wlan0] MAC: 00:90:4c:11:22:33 [ 9.456558] [ 9.456561] Dongle Host Driver, version 1.88.45.3 (r420671) [ 9.456565] Compiled in drivers/net/wireless/bcmdhd on Jun 26 2017 at 14:34:04 [ 9.472427] gpio ap6xxx_wl_regon set val 0, act val 0 [ 9.578054] [ap6xxx]: sdio wifi power state: off [ 9.583186] =========== WLAN placed in RESET ======== (WIFI启动加载正常) shell@astar-y3:/ $ lsmod gt82x 9849 0 - Live 0x00000000 sunxi_schw 12559 0 - Live 0x00000000 (O) cdc_ether 5099 0 - Live 0x00000000 rtl8150 9023 0 - Live 0x00000000 mcs7830 6292 0 - Live 0x00000000 qf9700 7805 0 - Live 0x00000000 asix 17150 0 - Live 0x00000000 usbnet 17700 4 cdc_ether,mcs7830,qf9700,asix, Live 0x00000000 sunxi_keyboard 3021 0 - Live 0x00000000 sw_device 13604 0 - Live 0x00000000 vfe_v4l2 445364 0 - Live 0x00000000 gc2035 12696 0 - Live 0x00000000 gc0308 10702 0 - Live 0x00000000 vfe_subdev 4523 3 vfe_v4l2,gc2035,gc0308, Live 0x00000000 vfe_os 4099 2 vfe_v4l2,vfe_subdev, Live 0x00000000 cci 21594 2 gc2035,gc0308, Live 0x00000000 videobuf_dma_contig 5535 1 vfe_v4l2, Live 0x00000000 videobuf_core 16520 2 vfe_v4l2,videobuf_dma_contig, Live 0x00000000 bcmdhd 556965 0 - Live 0x00000000 leds_sunxi 1351 0 - Live 0x00000000 mali 209914 20 - Live 0x00000000 (O) lcd 38180 0 - Live 0x00000000 disp 993096 8 mali,lcd, Live 0x00000000 nand 280622 0 - Live 0x00000000 (O) shell@astar-y3:/ $ (bcmdhd.ko这个驱动模块加载正常:) (BT没有打开,但是不停地打印BT超时出错,不知道是何解?) shell@astar-y3:/ $ [ 511.880344] [BT_LPM] bluesleep_tx_timer_expire: Tx timer expired [ 511.887326] [BT_LPM] bluesleep_tx_timer_expire: Tx has been idle 23、 由于此时WIFI出于记住上一次的状态的状态(打不开),所以需要重新刷镜像IMG,然后替换:bcmdhd.ko shell@astar-y3:/ $ shell@astar-y3:/ $ lsmod gt82x 9849 0 - Live 0x00000000 sunxi_schw 12559 0 - Live 0x00000000 (O) cdc_ether 5099 0 - Live 0x00000000 rtl8150 9023 0 - Live 0x00000000 mcs7830 6292 0 - Live 0x00000000 qf9700 7805 0 - Live 0x00000000 asix 17150 0 - Live 0x00000000 usbnet 17700 4 cdc_ether,mcs7830,qf9700,asix, Live 0x00000000 sunxi_keyboard 3021 0 - Live 0x00000000 sw_device 13604 0 - Live 0x00000000 vfe_v4l2 445364 0 - Live 0x00000000 gc2035 12696 0 - Live 0x00000000 gc0308 10702 0 - Live 0x00000000 vfe_subdev 4523 3 vfe_v4l2,gc2035,gc0308, Live 0x00000000 vfe_os 4099 2 vfe_v4l2,vfe_subdev, Live 0x00000000 cci 21594 2 gc2035,gc0308, Live 0x00000000 videobuf_dma_contig 5535 1 vfe_v4l2, Live 0x00000000 videobuf_core 16520 2 vfe_v4l2,videobuf_dma_contig, Live 0x00000000 bcmdhd 556965 0 - Live 0x00000000 leds_sunxi 1351 0 - Live 0x00000000 mali 209914 15 - Live 0x00000000 (O) lcd 38180 0 - Live 0x00000000 disp 993096 8 mali,lcd, Live 0x00000000 nand 280622 0 - Live 0x00000000 (O) shell@astar-y3:/ $ shell@astar-y3:/ $ shell@astar-y3:/ $ [ 110.012176] init: computing context for service '/system/bin/wpa_supplicant' [ 110.025400] init: starting 'p2p_supplicant' [ 110.039886] init: Created socket '/dev/socket/wpa_wlan0' with mode '660', user '1010', group '1010' [ 110.119751] dhd_conf_set_fw_name_by_chip: firmware_path=/system/vendor/modules/fw_bcm43438a0.bin [ 110.140144] [ 110.140153] Dongle Host Driver, version 1.88.45.3 (r420671) [ 110.140158] Compiled in drivers/net/wireless/bcmdhd on Jun 26 2017 at 14:34:04 [ 110.173523] wl_android_wifi_on in 1 [ 110.177409] wl_android_wifi_on in 2: g_wifi_on=0 [ 110.200103] gpio ap6xxx_wl_regon set val 1, act val 1 [ 110.280025] [BT_LPM] bluesleep_tx_timer_expire: Tx timer expired [ 110.286694] [BT_LPM] bluesleep_tx_timer_expire: Tx has been idle [ 110.355684] [ap6xxx]: sdio wifi power state: on [ 110.360930] =========== WLAN going back to live ======== [ 110.366925] sdio_reset_comm(): [ 110.370346] [mmc]: sdc1 set ios: clk 50000000Hz bm PP pm ON vdd 3.3V width 4 timing SD-HS(SDR25) dt B [ 110.380773] [mmc]: mclk 0xf1c2008c 0x8140030b [ 110.443029] [mmc]: sdc1 set ios: clk 50000000Hz bm PP pm ON vdd 3.3V width 4 timing SD-HS(SDR25) dt B [ 110.454758] [mmc]: mclk 0xf1c2008c 0x8140030b [ 110.516097] [mmc]: sdc1 set ios: clk 150000Hz bm PP pm ON vdd 3.3V width 4 timing SD-HS(SDR25) dt B [ 110.530958] [mmc]: mclk 0xf1c2008c 0x80430309 [ 110.592013] [mmc]: sdc1 set ios: clk 150000Hz bm PP pm ON vdd 3.3V width 4 timing SD-HS(SDR25) dt B [ 110.603518] [mmc]: mclk 0xf1c2008c 0x80030009 [ 110.681418] mmc1: queuing unknown CIS tuple 0x80 (2 bytes) [ 110.690726] mmc1: queuing unknown CIS tuple 0x80 (3 bytes) [ 110.700331] mmc1: queuing unknown CIS tuple 0x80 (3 bytes) [ 110.712218] mmc1: queuing unknown CIS tuple 0x80 (7 bytes) [ 110.894520] [mmc]: sdc1 set ios: clk 150000Hz bm PP pm ON vdd 3.3V width 4 timing SD-HS(SDR25) dt B [ 110.904933] [mmc]: mclk 0xf1c2008c 0x80030009 [ 110.964907] [mmc]: sdc1 set ios: clk 50000000Hz bm PP pm ON vdd 3.3V width 4 timing SD-HS(SDR25) dt B [ 110.975514] [mmc]: mclk 0xf1c2008c 0x8100000b [ 111.035618] [mmc]: sdc1 set ios: clk 50000000Hz bm PP pm ON vdd 3.3V width 4 timing SD-HS(SDR25) dt B [ 111.046398] [mmc]: mclk 0xf1c2008c 0x8140030b [ 111.108547] [ 111.108566] [ 111.108579] dhd_bus_devreset: == WLAN ON == [ 111.116882] dhd_bus_devreset called when dongle is not in reset [ 111.123683] Will call dhd_bus_start instead [ 111.128637] dhd_conf_set_fw_name_by_chip: firmware_path=/system/vendor/modules/fw_bcm43438a0.bin [ 111.140963] dhd_conf_download_config: Ignore config file /system/vendor/modules/config.txt [ 111.151802] Final fw_path=/system/vendor/modules/fw_bcm43438a0.bin [ 111.158689] Final nv_path=/system/vendor/modules/nvram_ap6210.txt [ 111.165542] Final conf_path=/system/vendor/modules/config.txt [ 111.257577] dhdsdio_download_nvram: Open nvram file failed /system/vendor/modules/nvram_ap6210.txt [ 111.268309] _dhdsdio_download_firmware: dongle nvram file download failed [ 111.276022] dhd_bus_start: dhdsdio_probe_download failed. firmware = /system/vendor/modules/fw_bcm43438a0.bin nvram = /system/vendor/modules/nvram_ap6210.txt config = /system/vendor/modules/config.txt [ 111.295979] dhd_bus_devreset: dhd_bus_start fail with -1 [ 111.304154] dhd_dev_reset: dhd_bus_devreset: -1 [ 111.309190] dhd_prot_ioctl : bus is down. we have nothing to do [ 111.330328] dhd_bus_devreset: WLAN OFF DONE [ 111.335225] gpio ap6xxx_wl_regon set val 0, act val 0 [ 111.472499] [ap6xxx]: sdio wifi power state: off [ 111.477661] =========== WLAN placed in RESET ======== [ 111.483304] wl_android_wifi_on: Failed [ 111.487473] wl_android_wifi_off in 1 [ 111.491478] wl_android_wifi_off in 2: g_wifi_on=0 [ 111.496711] wl_android_wifi_off out [ 111.509335] init: waitpid returned pid 1211, status = 0000ff00 [ 111.516072] init: process 'p2p_supplicant', pid 1211 exited shell@astar-y3:/ $ shell@astar-y3:/ $ 24、定位问题:dhd_bus_devreset: dhd_bus_start fail with -1 rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ cd linux-3.4/drivers/net/wireless/bcmdhd/ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ grep "dhd_bus_start fail with" . -R ./dhd_sdio.c: DHD_ERROR(("%s: dhd_bus_start fail with %d\n", 匹配到二进制文件 ./dhd_sdio.o 匹配到二进制文件 ./bcmdhd.o 匹配到二进制文件 ./bcmdhd.ko rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee$ cd linux-3.4/drivers/net/wireless/bcmdhd/ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ grep "dhd_bus_start fail with" . -R ./dhd_sdio.c: DHD_ERROR(("%s: dhd_bus_start fail with %d\n", 匹配到二进制文件 ./dhd_sdio.o 匹配到二进制文件 ./bcmdhd.o 匹配到二进制文件 ./bcmdhd.ko rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) { …… dhd_conf_set_fw_name_by_chip(dhdp, fw_path, firmware_path); if ((bcmerror = dhd_bus_start(dhdp)) != 0) DHD_ERROR(("%s: dhd_bus_start fail with %d\n", __FUNCTION__, bcmerror)); } } return bcmerror; } rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ grep dhd_bus_start . -R ./dhd_sdio.c: if ((ret = dhd_bus_start(bus->dhd)) != 0) { ./dhd_sdio.c: DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__)); ./dhd_sdio.c: DHD_ERROR(("Will call dhd_bus_start instead\n")); ./dhd_sdio.c: if ((bcmerror = dhd_bus_start(dhdp)) != 0) ./dhd_sdio.c: DHD_ERROR(("%s: dhd_bus_start fail with %d\n", ./dhd_sdio - 副本.c: if ((ret = dhd_bus_start(bus->dhd)) != 0) { ./dhd_sdio - 副本.c: DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__)); ./dhd_sdio - 副本.c: DHD_ERROR(("Will call dhd_bus_start instead\n")); ./dhd_sdio - 副本.c: if ((bcmerror = dhd_bus_start(dhdp)) != 0) ./dhd_sdio - 副本.c: DHD_ERROR(("%s: dhd_bus_start fail with %d\n", ./dhd_sdio - 副本 (2).c: if ((ret = dhd_bus_start(bus->dhd)) != 0) { ./dhd_sdio - 副本 (2).c: DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__)); ./dhd_sdio - 副本 (2).c: DHD_ERROR(("Will call dhd_bus_start instead\n")); ./dhd_sdio - 副本 (2).c: if ((bcmerror = dhd_bus_start(dhdp)) != 0) ./dhd_sdio - 副本 (2).c: DHD_ERROR(("%s: dhd_bus_start fail with %d\n", ./dhd.h:extern int dhd_bus_start(dhd_pub_t *dhdp); ./wl_android.c:/* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first ./dhd_linux.c: if ((ret = dhd_bus_start(&dhd->pub)) != 0) { ./dhd_linux.c: /* dhd_prot_init has been called in dhd_bus_start or wl_android_wifi_on */ ./dhd_linux.c:dhd_bus_start(dhd_pub_t *dhdp) rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4/drivers/net/wireless/bcmdhd$ 定位到这里: int dhd_bus_start(dhd_pub_t *dhdp) { …… /* try to download image and nvram to the dongle */ if ((dhd->pub.busstate == DHD_BUS_DOWN) && (fw_path[0] != '\0') && (nv_path[0] != '\0')) { #ifdef SHOW_NVRAM_TYPE { /* Show nvram type in the kernel log */ int i; for (i = 0; nv_path[i] != '\0'; ++i) { if (nv_path[i] == '.') { ++i; break; } } DHD_ERROR(("%s: nvram_type = [%s]\n", __FUNCTION__, &nv_path[i])); } #endif /* SHOW_NVRAM_TYPE */ /* wake lock moved to dhdsdio_download_firmware */ if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh, fw_path, nv_path, conf_path))) { DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s config = %s\n", __FUNCTION__, fw_path, nv_path, conf_path)); #ifdef DHDTHREAD if (dhd->threads_only) dhd_os_sdunlock(dhdp); #endif /* DHDTHREAD */ // 2017/6/23 18:40 wenyuanbo download ap6212 fail not return error!!!! //return -1; } } …… return 0; } 由于ap6212没有config.txt文件,下载肯定会出错,比对全志R16平台去AP6212的处理,关闭这里: //return -1; 25、 shell@astar-y3:/ $ shell@astar-y3:/ $ [ 110.012176] init: computing context for service '/system/bin/wpa_supplicant' [ 110.025400] init: starting 'p2p_supplicant' [ 110.039886] init: Created socket '/dev/socket/wpa_wlan0' with mode '660', user '1010', group '1010' [ 110.119751] dhd_conf_set_fw_name_by_chip: firmware_path=/system/vendor/modules/fw_bcm43438a0.bin [ 110.140144] [ 110.140153] Dongle Host Driver, version 1.88.45.3 (r420671) [ 110.140158] Compiled in drivers/net/wireless/bcmdhd on Jun 26 2017 at 14:34:04 [ 110.173523] wl_android_wifi_on in 1 [ 110.177409] wl_android_wifi_on in 2: g_wifi_on=0 [ 110.200103] gpio ap6xxx_wl_regon set val 1, act val 1 [ 110.280025] [BT_LPM] bluesleep_tx_timer_expire: Tx timer expired [ 110.286694] [BT_LPM] bluesleep_tx_timer_expire: Tx has been idle [ 110.355684] [ap6xxx]: sdio wifi power state: on [ 110.3
《深入理解Android:卷2》是“深入理解Android”系列的第2本,第1本书上市后获得广大读者高度评价,在Android开发者社群内口口相传。《深入理解Android:卷2》不仅继承了第1本书的优点并改正了其在细微处存在的一些不足,而且还在写作的总体思想上进行了创新,更强调从系统设计者的角度去分析Android系统中各个模块内部的实现原理和工作机制。从具体内容上讲,重点是Android Framework的Java层,对Java层涉及的核心模块和服务进行了深入而细致的分析。通过《深入理解Android:卷2》,读者不仅能对Android系统本身有更深入的理解,而且还能掌握分析大型复杂源代码的能力。《深入理解Android:卷2》共8章:第1章介绍了阅读本书所需要做的准备工作,包括Android 4.0源码的下载和编译、Eclipse环境的搭建,以及Android系统进程(system_process)的调试等;第2章对Java Binder和MessageQueue的实现进行了深入分析;第3章仔细剖析了SystemServer的工作原理,这些服务包括EntropyService、DropboxManagerService、DiskStatsService、DeviceStorageMonitorService、SamplingProfilerService和ClipboardService;第4章对系统中负责Package信息查询和APK安装、卸载、更新等工作的服务PackageManagerService进行了详细分析;第5章则对Android系统中负责电源管理的核心服务 PowerManagerService的原理进行了一番深入的分析;第6章以ActivityManagerService为分析重点,它的启动、Activity的创建和启动、BroadcastReceiver的工作原理、Android中的进程管理等内容展开了较为深入的研究;第7章对ContentProvider的创建和启动、SQLite、Cursor query和close的实现等进行了深入分析;第8章以ContentService和AccountManagerService为分析对象,介绍了数据更新通知机制的实现,以及账户管理和数据同步等相关知识。
ERDAS2011破解安装法 为保证安装成功,先断网!并删掉老版本erdas及其服务器痕迹,最好能在360里进行。不放心的话,还可彻底关掉防火墙和病毒软件。 ERDAS2011破解安装步骤如下: 1、首先装ERDAS Foundation 2011 2、然后装ERDAS IMAGINE 2011 3、然后选装其它功能软件:LPS 2011 (可选)、ERDAS ER Mapper 2011 (可选)和ERDAS APOLLO 2011 (可选)等。 注意:如果已装了ARCGIS,就不必再装Geodatabase Support。第三步安装,不太苛刻,可稍后两步。 4、然后装erdas Imagine Desktop V11.0.2升级补丁 5、将"Erdas2011 crack\patched files"下"ERDAS Desktop 2011"里面的文件拷贝到erdas安装目录并覆盖之。【破解1】 6、然后装ERDAS_Extensions2011_ArcGIS10及其erdas Extensions 2011 for arcgis 10 – SP1 Update升级补丁 7、将"ERDAS Extensions 2011" 拷贝到Extensions的安装目录并覆盖之。【破解2】 其它可选部件:安装并为app和Plugins打补丁。 Erdas Orima DP for LPS 2011 V11.0 PRO600 2011 Plugin for MicroStation V8 PRO600 2011 Plugin for MicroStation V8 XM Edition PRO600 Fundamentals 2011 Plugin for Bentley PowerMap XM 8.将“License patch”文件下的"Win32Release"全拷贝到 C:\Program Files\ERDAS\Shared\licensing\bin 并覆盖之!【破解3】 9. 于此打开"erdas.dat" ,并将 "YOUR_HOST"替换为你自己的主机名。 10. 在"C:\Program Files (x86)\ERDAS\Shared\Licensing\bin\Win32Release"之下,点开Lmtools.exe,找到Config Services菜单,将 "ERDAS License Service" 作为一个新服务名称,并设置好“三项”,点击并保存Service。然后用查看lmgrd.exe,Borrower许可文件erdas.dat和日志文件Log.log。 现在极为重要!!----点击 "Use Services" ,选上"start server on powerup"(开机服务生效),然后再点保存Service。 11. 然后重启电脑,在控制面板下查看服务Services启动与否(一般是成功的,否则再设为启动状态)。 然后在那文件内打开"LicAdmin.exe",打开Server菜单,点击Add remote server,输入你的主机名或IP地址,通道数设为1700,点OK确定!于是在License Sources下就可查看到全部功能解锁了! 【注意】不要通过Lmtools,而通过控制面板下/管理工具/服务,找到并设置Service Manager Configuration。 12.打开ERDAS IMAGINE 2011享用吧,到此安装成功!
《深入理解Android:卷2》是“深入理解Android”系列的第2本,第1本书上市后获得广大读者高度评价,在Android开发者社群内口口相传。《深入理解Android:卷2》不仅继承了第1本书的优点并改正了其在细微处存在的一些不足,而且还在写作的总体思想上进行了创新,更强调从系统设计者的角度去分析Android系统中各个模块内部的实现原理和工作机制。从具体内容上讲,重点是Android Framework的Java层,对Java层涉及的核心模块和服务进行了深入而细致的分析。通过《深入理解Android:卷2》,读者不仅能对Android系统本身有更深入的理解,而且还能掌握分析大型复杂源代码的能力。 《深入理解Android:卷2》共8章:第1章介绍了阅读本书所需要做的准备工作,包括Android 4.0源码的下载和编译、Eclipse环境的搭建,以及Android系统进程(system_process)的调试等;第2章对Java Binder和MessageQueue的实现进行了深入分析;第3章仔细剖析了SystemServer的工作原理,这些服务包括EntropyService、DropboxManagerService、DiskStatsService、DeviceStorageMonitorService、SamplingProfilerService和ClipboardService;第4章对系统中负责Package信息查询和APK安装、卸载、更新等工作的服务PackageManagerService进行了详细分析;第5章则对Android系统中负责电源管理的核心服务 PowerManagerService的原理进行了一番深入的分析;第6章以ActivityManagerService为分析重点,它的启动、Activity的创建和启动、BroadcastReceiver的工作原理、Android中的进程管理等内容展开了较为深入的研究;第7章对ContentProvider的创建和启动、SQLite、Cursor query和close的实现等进行了深入分析;第8章以ContentService和AccountManagerService为分析对象,介绍了数据更新通知机制的实现,以及账户管理和数据同步等相关知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值