前言
定制系统api,首先遵照着AIDL-Service-Manager-App的原则,每一步去实现,本次教程首先定义的系统API接口如下说明:
| 方法名(void) | 参数(String) | 参数(boolean) |
|---|---|---|
| setSystemBarShow | type | visibility |
type
- NavigationBar 底部导航栏
- StatusBar 顶部状态栏
- DrowDown 下拉框显示
visibility
- true 显示
- false 隐藏
IWSettingsService.aidl
创建新的AIDL文件
路径:framework/base/core/java/android/os/IWSettingsService.aidl
代码如下,按照上述定义的函数定义接口即可
package android.os;
/**
* @hide
*/
interface IWSettingsService
{
void setSystemBarShow(String type,boolean visibility);
}
注意:必须用@hide注解,否则会编译失败
WSettingsService.java
创建对应aidl实现的是service实现的类
路径:framework/base/services/core/java/com/android/server/WSettingsService.java
根据AIDL的接口,我们采用的埋点的方式,通过广播的方式,将需要控制的信息传递给对应的类,这些对应的类的埋点位置,后续会介绍,大家注意的地方这里采用的是隐式广播的方式
package com.android.server;
import android.content.Context;
import android.util.Slog;
import android.os.IWSettingsService;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
public class WSettingsService extends IWSettingsService.Stub
{
private static final String TAG = "WSettingsService";
private Context mContext;
public WSettingsService(Context context)
{
this.mContext = context;
}
public void setSystemBarShow(String type,boolean visibility)
{
if(type.equals("NavigationBar"))
{
if(visibility)
{
showNavigationBar();
}
else
{
hideNavigationBar();
}
}
else if(type.equals("StatusBar"))
{
if(visibility)
{
showStatusBar();
}
else
{
hideStatusBar();
}
}
else if(type.equals("DropDown"))
{
if(visibility)
{
showDropDown();
}
else
{
hideDropDown();
}
}
}
private void hideNavigationBar()
{
// 隐藏导航栏
Intent intent = new Intent();
intent.setPackage("com.android.systemui");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("action.ACTION_API_HIDE_NAVIGATION");
mContext.sendBroadcast(intent);
}
private void showNavigationBar()
{
// 显示导航栏
Intent intent = new Intent();
intent.setPackage("com.android.systemui");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("action.ACTION_API_SHOW_NAVIGATION");
mContext.sendBroadcast(intent);
}
private void hideStatusBar()
{
// 隐藏状态栏
Intent intent = new Intent();
intent.setPackage("com.android.systemui");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("action.ACTION_API_HIDE_STATUS_BAR");
mContext.sendBroadcast(intent);
}
private void showStatusBar()
{
// 显示状态栏
Intent intent = new Intent();
intent.setPackage("com.android.systemui");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("action.ACTION_API_SHOW_STATUS_BAR");
mContext.sendBroadcast(intent);
}
private void hideDropDown()
{
//禁止下拉框
Intent intent = new Intent();
intent.setPackage("com.android.systemui");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("action.ACTION_API_HIDE_DROP_DOWN_BOX");
intent.putExtra("state", "true");
mContext.sendBroadcast(intent);
}
private void showDropDown()
{
//允许下拉框
Intent intent = new Intent();
intent.setPackage("com.android.systemui");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("action.ACTION_API_HIDE_DROP_DOWN_BOX");
intent.putExtra("state", "false");
mContext.sendBroadcast(intent);
}
};
SystemServer.java
注册上述服务
路径:framework/base/services/java/com/android/server/SystemServer.java
函数注册位置
private void startOtherServices(@NonNull TimingsTraceAndSlog t)
t.traceBegin("Start WSettingsService");
try {
ServiceManager.addService(Context.WSETTINGS_SERVICE, new WSettingsService(context));
}
catch (Throwable e)
{
Slog.e(TAG, "Failure starting WSettingsService", e);
}
t.traceEnd();
启动服务生效
路径: core/java/android/app/SystemServiceRegistry.java
...
// Not instantiable.
private SystemServiceRegistry() { }
static {
registerService(Context.WSETTINGS_SERVICE, WSettingsManager.class,
new CachedServiceFetcher<WSettingsManager>(){
@Override
public WSettingsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getService(Context.WSETTINGS_SERVICE);
IWSettingsService service = IWSettingsService.Stub.asInterface(b);
return new WSettingsManager(ctx, service);
}});
//end, add by xiaoxuan
...
WSettingsManager.java
具体实现服务中接口的方法
路径:framework/base/core/java/android/app/WSettingsManager.java
package android.app;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;
import android.os.Build;
import android.os.IWSettingsService;
import android.annotation.NonNull;
import android.annotation.Nullable;
import java.lang.String;
public class WSettingsManager {
private static String TAG = "WSettingsManager";
IWSettingsService mService; //AIDL
/* 下边的hide是隐藏的意思,因为系统服务注册函数也是hide的,所以这里需要添加hide,不添加的话编译会报错 */
/**
* @hide
*/
public WSettingsManager(Context ctx, IWSettingsService service){
mService=service;
}
public void setSystemBarShow(@NonNull String type,boolean visibility)
{
try{
mService.setSystemBarShow(type,visibility);
}catch(Exception e){
e.printStackTrace();
}
}
}
引用类
framework/base/core/java/android/provider/Settings.java
// by xiaoxuan
/**
* add by xiaoxuan
* Disable drop-down box
* @hide
*/
// 必须加上@hide注解否则编译报错
public static final String SYSTEM_HIDE_DROP_DOWN_BOX = "hide_dro_down_box";
core/java/android/content/Context.java
/** @hide */
@StringDef(suffix = { "_SERVICE" }, value = {
...
WSETTINGS_SERVICE,
...
public static final String WSETTINGS_SERVICE = "wsettings";
埋点类
framework/base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
import android.provider.Settings;
// by xiaoxuan
private Context mContext;
public CommandQueue(Context context) {
this(context, null);
mContext = context;
}
public CommandQueue(Context context, ProtoTracer protoTracer) {
mProtoTracer = protoTracer;
context.getSystemService(DisplayManager.class).registerDisplayListener(this, mHandler);
// We always have default display.
setDisabled(DEFAULT_DISPLAY, DISABLE_NONE, DISABLE2_NONE);
mContext = context;
}
// TODO(b/118592525): add multi-display support if needed.
public boolean panelsEnabled() {
final int disabled1 = getDisabled1(DEFAULT_DISPLAY);
final int disabled2 = getDisabled2(DEFAULT_DISPLAY);
//return (disabled1 & StatusBarManager.DISABLE_EXPAND) == 0
// && (disabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0
// && !ONLY_CORE_APPS;
//add by xiaoxuan
boolean isHide = Settings.System.getInt(
mContext.getContentResolver(), Settings.SYSTEM_HIDE_DROP_DOWN_BOX, 0) != 0;
if(isHide)
{
return false;
}
else
{
return (disabled1 & StatusBarManager.DISABLE_EXPAND) == 0
&& (disabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0
&& !ONLY_CORE_APPS;
}
//end, add by xiaoxuan
}
framework/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
public static final String ACTION_API_HIDE_NAVIGATION = "action.ACTION_API_HIDE_NAVIGATION"; //隐藏导航栏广播
public static final String ACTION_API_SHOW_NAVIGATION = "action.ACTION_API_SHOW_NAVIGATION"; //显示导航栏广播
public static final String ACTION_API_HIDE_STATUS_BAR = "action.ACTION_API_HIDE_STATUS_BAR"; //隐藏狀態广播
public static final String ACTION_API_SHOW_STATUS_BAR = "action.ACTION_API_SHOW_STATUS_BAR"; //顯示狀態蘭广播
public static final String ACTION_API_HIDE_DROP_DOWN_BOX = "action.ACTION_API_HIDE_DROP_DOWN_BOX"; //下拉框廣播
private boolean mHideNavStatus = true;
protected void registerBroadcastReceiver() {
IntentFilter filter = new IntentFilter();
//add by xiaoxuan 添加到广播队列里
filter.addAction(ACTION_API_HIDE_NAVIGATION);
filter.addAction(ACTION_API_SHOW_NAVIGATION);
filter.addAction(ACTION_API_HIDE_STATUS_BAR);
filter.addAction(ACTION_API_SHOW_STATUS_BAR);
filter.addAction(ACTION_API_HIDE_DROP_DOWN_BOX);
//------------------------------
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG);
mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL);
}
private void hideNavigation() {
if (mHideNavStatus){
//Log.d(TAG,"====== hide Navigation ======");
NavigationBarView mNavigationBarView = mNavigationBarController.getDefaultNavigationBarView();
if (mNavigationBarView != null)
mNavigationBarController.hideNavigationBar();
mHideNavStatus = false;
}
}
private void showNavigation() {
if (!mHideNavStatus){
//Log.d(TAG,"====== api show Navigation ======");
NavigationBarView mNavigationBarView = mNavigationBarController.getDefaultNavigationBarView();
if (mNavigationBarView == null)
mNavigationBarController.createNavigationBars(true,null);
mHideNavStatus = true;
}
}
private void showStatusBar() {
if (mStatusBarView!=null){
//Log.d(TAG,"====== show StatusBar ======");
mStatusBarView.setVisibility(View.VISIBLE);
}
}
private void hideStatusBar() {
if (mStatusBarView != null){
//Log.d(TAG,"====== hide StatusBar ======");
mStatusBarView.setVisibility(View.GONE);
}
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.v(TAG, "onReceive: " + intent);
String action = intent.getAction();
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
KeyboardShortcuts.dismiss();
if (mRemoteInputManager.getController() != null) {
mRemoteInputManager.getController().closeRemoteInputs();
}
if (mBubbleController.isStackExpanded()) {
mBubbleController.collapseStack();
}
if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) {
int flags = CommandQueue.FLAG_EXCLUDE_NONE;
String reason = intent.getStringExtra("reason");
if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
}
mShadeController.animateCollapsePanels(flags);
}
}
// by xiaoxuan
else if(ACTION_API_HIDE_NAVIGATION.equals(action)) {
hideNavigation(); //隐藏导航栏
}
else if(ACTION_API_SHOW_NAVIGATION.equals(action)) {
showNavigation(); //显示导航栏
}
else if(ACTION_API_HIDE_STATUS_BAR.equals(action)) {
hideStatusBar();
}
else if(ACTION_API_SHOW_STATUS_BAR.equals(action)) {
showStatusBar();
}
else if(ACTION_API_HIDE_DROP_DOWN_BOX.equals(action)) {
String state= intent.getStringExtra("state"); //解析出应用发送过来的参数值
if (state != null && "true".equals(state)) {
Settings.System.putInt(context.getContentResolver(), Settings.SYSTEM_HIDE_DROP_DOWN_BOX, 1); //禁止下拉框
} else {
Settings.System.putInt(context.getContentResolver(), Settings.SYSTEM_HIDE_DROP_DOWN_BOX, 0); //允许下拉框
}
}
//--------------------------------------------------
else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
if (mNotificationShadeWindowController != null) {
mNotificationShadeWindowController.setNotTouchable(false);
}
if (mBubbleController.isStackExpanded()) {
mBubbleController.collapseStack();
}
finishBarAnimations();
resetUserExpandedStates();
}
packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
/**
* by xiaoxuan
* hide 导航栏
* */
public void hideNavigationBar() {
Display[] displays = mDisplayManager.getDisplays();
for (Display display : displays) {
removeNavigationBar(display.getDisplayId());
}
}
到此代码部分整理完毕,请先执行make update-api更新系统API