、
这篇文章针对的是系统权限的app,因为
Intent.ACTION_AIRPLANE_MODE_CHANGED 在AndroidManifest.xml文件中属于<protected-broadcat/>,需要权限需要高权限才能操作,
//Intent.class
public class Intent implements Parcelable, Cloneable {
...
public static final String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";
...
}
// framework/base/core/res/AndroidManifest.xml
<protected-broadcast android:name="android.intent.action.AIRPLANE_MODE" />
应为Android 发送广播最终要走 ActivityManagerService 的broadcastIntentLocked 方法,我贴一段发送广播的代码,在里面有一段代码是判断当前 app的 uid权限的,如果权限不够则直接跑出异常
@GuardedBy("this")
final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
...
final boolean isCallerSystem;
switch (UserHandle.getAppId(callingUid)) {
case ROOT_UID:
case SYSTEM_UID:
case PHONE_UID:
case BLUETOOTH_UID:
case NFC_UID:
case SE_UID:
isCallerSystem = true;
break;
default:
isCallerSystem = (callerApp != null) && callerApp.persistent;
break;
}
// First line security check before anything else: stop non-system apps from
// sending protected broadcasts.
if (!isCallerSystem) {
if (isProtectedBroadcast) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " from pid="
+ callingPid + ", uid=" + callingUid;
Slog.w(TAG, msg);
throw new SecurityException(msg);
} else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
// Special case for compatibility: we don't want apps to send this,
// but historically it has not been protected and apps may be using it
// to poke their own app widget. So, instead of making it protected,
// just limit it to the caller.
if (callerPackage == null) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " from unknown caller.";
Slog.w(TAG, msg);
throw new SecurityException(msg);
} else if (intent.getComponent() != null) {
// They are good enough to send to an explicit component... verify
// it is being sent to the calling app.
if (!intent.getComponent().getPackageName().equals(
callerPackage)) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " to "
+ intent.getComponent().getPackageName() + " from "
+ callerPackage;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
} else {
// Limit broadcast to their own package.
intent.setPackage(callerPackage);
}
}
}
...
return ActivityManager.BROADCAST_SUCCESS;
}
/**
* 飞行模式开关
* @param setAirPlane
*/
public static void toggleAirplaneMode(Context context,boolean setAirPlane) {
Log.d(TAG, "toggleAirplaneMode: "+setAirPlane);
String value = setAirPlane?"1":"0";
Log.d(TAG, "toggleAirplaneMode: "+value);
Settings.Global.putString( context.getContentResolver(),Settings.Global.AIRPLANE_MODE_ON,value );
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
context.sendBroadcast(intent);
}