com.gxatek.cockpit.account E/AndroidRuntime: FATAL EXCEPTION: main Process: com.gxatek.cockpit.account, PID: 17800 java.lang.SecurityException: Permission Denial: not allowed to send broadcast com.gxa.cockpit.hvac.service from pid=17800, uid=10028 at android.os.Parcel.createException(Parcel.java:1950) at android.os.Parcel.readException(Parcel.java:1918) at android.os.Parcel.readException(Parcel.java:1868) at android.app.IActivityManager$Stub$Proxy.broadcastIntent(IActivityManager.java:3894) at android.app.ContextImpl.sendBroadcast(ContextImpl.java:1009) at android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:444) at com.gxatek.cockpit.account.model.OpenAppModel.gotoHvac(OpenAppModel.java:107) at com.gxatek.cockpit.account.presentation.presenter.HomePresenter.openHvacHmi(HomePresenter.java:306) at com.gxatek.cockpit.account.presentation.view.fragment.HomeAccountFragment.onClick(HomeAccountFragment.java:502) at android.view.View.performClick(View.java:6597) at android.view.View.performClickInternal(View.java:6574) at android.view.View.access$3100(View.java:778) at android.view.View$PerformClick.run(View.java:25885) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6718) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) Caused by: android.os.RemoteException: Remote stack trace: at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:21358) at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:21987) at android.app.IActivityManager$Stub.onTransact$broadcastIntent$(IActivityManager.java:10171) at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:167) at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3291)
2.问题调查
2.1 源码分析
1 2 3 4 5
// 从log获得到关键信息如下, // 发送受保护的广播名字:com.gxa.cockpit.hvac.service // 账号的pid:17800 // 账号的uid:10028 Permission Denial: not allowed to send broadcast com.gxa.cockpit.hvac.service from pid=17800, uid=10028
finalintbroadcastIntentLocked(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){ ...... // Verify that protected broadcasts are only being sent by system code, // and that system code is only sending protected broadcasts. // AndroidManifest.xml中定义了<protected-broadcast>定义的受保护广播 finalboolean isProtectedBroadcast; try { isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action); } catch (RemoteException e) { Slog.w(TAG, "Remote exception", e); return ActivityManager.BROADCAST_SUCCESS; }
// 根据uid和应用中persistent标志位判断当前进程是不是isCallerSystem finalboolean 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); thrownew SecurityException(msg);
} elseif (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) { ...... }