private final void addActiveOwnerLocked(int uid, String pkg) { final IPackageManager pm = AppGlobals.getPackageManager(); final int targetUserHandle = UserHandle.getCallingUserId(); final long oldIdentity = Binder.clearCallingIdentity(); try { PackageInfo pi = pm.getPackageInfo(pkg, 0, targetUserHandle); if (pi == null) { throw new IllegalArgumentException("Unknown package " + pkg); } if (!UserHandle.isSameApp(pi.applicationInfo.uid, uid)) { throw new SecurityException("Calling uid " + uid + " does not own package " + pkg); } } catch (RemoteException e) { // Can't happen; the package manager is in the same process } finally { Binder.restoreCallingIdentity(oldIdentity); } PerUserClipboard clipboard = getClipboard(); if (clipboard.primaryClip != null && !clipboard.activePermissionOwners.contains(pkg)) { final int N = clipboard.primaryClip.getItemCount(); for (int i = 0; i < N; i++) { grantItemLocked(clipboard.primaryClip.getItemAt(i), pkg); } clipboard.activePermissionOwners.add(pkg); } }
void resetProcessCrashTimeLocked(boolean resetEntireUser, int appId, int userId) { final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap(); for (int ip = pmap.size() - 1; ip >= 0; ip--) { SparseArray<Long> ba = pmap.valueAt(ip); for (int i = ba.size() - 1; i >= 0; i--) { boolean remove = false; final int entUid = ba.keyAt(i); if (!resetEntireUser) { if (userId == UserHandle.USER_ALL) { if (UserHandle.getAppId(entUid) == appId) { remove = true; } } else { if (entUid == UserHandle.getUid(userId, appId)) { remove = true; } } } else if (UserHandle.getUserId(entUid) == userId) { remove = true; } if (remove) { ba.removeAt(i); } } if (ba.size() == 0) { pmap.removeAt(ip); } } }
/** * @hide Note that UserHandle.CURRENT will be interpreted at the time the activity is started, not * when the pending intent is created. */ public static PendingIntent getActivitiesAsUser( Context context, int requestCode, @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) { String packageName = context.getPackageName(); String[] resolvedTypes = new String[intents.length]; for (int i = 0; i < intents.length; i++) { intents[i].migrateExtraStreamToClipData(); intents[i].prepareToLeaveProcess(); resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver()); } try { IIntentSender target = ActivityManagerNative.getDefault() .getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY, packageName, null, null, requestCode, intents, resolvedTypes, flags, options, user.getIdentifier()); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { } return null; }
/** * @hide Note that UserHandle.CURRENT will be interpreted at the time the broadcast is sent, not * when the pending intent is created. */ public static PendingIntent getBroadcastAsUser( Context context, int requestCode, Intent intent, int flags, UserHandle userHandle) { String packageName = context.getPackageName(); String resolvedType = intent != null ? intent.resolveTypeIfNeeded(context.getContentResolver()) : null; try { intent.prepareToLeaveProcess(); IIntentSender target = ActivityManagerNative.getDefault() .getIntentSender( ActivityManager.INTENT_SENDER_BROADCAST, packageName, null, null, requestCode, new Intent[] {intent}, resolvedType != null ? new String[] {resolvedType} : null, flags, null, userHandle.getIdentifier()); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { } return null; }
/** * Retrieve a PendingIntent that will start a service, like calling {@link Context#startService * Context.startService()}. The start arguments given to the service will come from the extras of * the Intent. * * <p class="note">For security reasons, the {@link android.content.Intent} you supply here should * almost always be an <em>explicit intent</em>, that is specify an explicit component to be * delivered to through {@link Intent#setClass(android.content.Context, Class) Intent.setClass} * * @param context The Context in which this PendingIntent should start the service. * @param requestCode Private request code for the sender * @param intent An Intent describing the service to be started. * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, {@link * #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, or any of the flags as supported by * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts of the intent that * can be supplied when the actual send happens. * @return Returns an existing or new PendingIntent matching the given parameters. May return null * only if {@link #FLAG_NO_CREATE} has been supplied. */ public static PendingIntent getService( Context context, int requestCode, @NonNull Intent intent, @Flags int flags) { String packageName = context.getPackageName(); String resolvedType = intent != null ? intent.resolveTypeIfNeeded(context.getContentResolver()) : null; try { intent.prepareToLeaveProcess(); IIntentSender target = ActivityManagerNative.getDefault() .getIntentSender( ActivityManager.INTENT_SENDER_SERVICE, packageName, null, null, requestCode, new Intent[] {intent}, resolvedType != null ? new String[] {resolvedType} : null, flags, null, UserHandle.myUserId()); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { } return null; }
final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) { if (r.nextReceiver > 0) { Object curReceiver = r.receivers.get(r.nextReceiver - 1); if (curReceiver instanceof BroadcastFilter) { BroadcastFilter bf = (BroadcastFilter) curReceiver; EventLog.writeEvent( EventLogTags.AM_BROADCAST_DISCARD_FILTER, bf.owningUserId, System.identityHashCode(r), r.intent.getAction(), r.nextReceiver - 1, System.identityHashCode(bf)); } else { ResolveInfo ri = (ResolveInfo) curReceiver; EventLog.writeEvent( EventLogTags.AM_BROADCAST_DISCARD_APP, UserHandle.getUserId(ri.activityInfo.applicationInfo.uid), System.identityHashCode(r), r.intent.getAction(), r.nextReceiver - 1, ri.toString()); } } else { Slog.w(TAG, "Discarding broadcast before first receiver is invoked: " + r); EventLog.writeEvent( EventLogTags.AM_BROADCAST_DISCARD_APP, -1, System.identityHashCode(r), r.intent.getAction(), r.nextReceiver, "NONE"); } }
/** * @hide Note that UserHandle.CURRENT will be interpreted at the time the activity is started, not * when the pending intent is created. */ public static PendingIntent getActivityAsUser( Context context, int requestCode, @NonNull Intent intent, int flags, Bundle options, UserHandle user) { String packageName = context.getPackageName(); String resolvedType = intent != null ? intent.resolveTypeIfNeeded(context.getContentResolver()) : null; try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(); IIntentSender target = ActivityManagerNative.getDefault() .getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY, packageName, null, null, requestCode, new Intent[] {intent}, resolvedType != null ? new String[] {resolvedType} : null, flags, options, user.getIdentifier()); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { } return null; }
@Override public String toString() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { return mUser.toString(); } else { return ""; } }
@Override public int hashCode() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { return mUser.hashCode(); } else { return 0; } }
boolean updateService(Context context, ActivityManager.RunningServiceInfo service) { final PackageManager pm = context.getPackageManager(); boolean changed = false; ServiceItem si = mServices.get(service.service); if (si == null) { changed = true; si = new ServiceItem(mUserId); si.mRunningService = service; try { si.mServiceInfo = ActivityThread.getPackageManager() .getServiceInfo( service.service, PackageManager.GET_UNINSTALLED_PACKAGES, UserHandle.getUserId(service.uid)); if (si.mServiceInfo == null) { Log.d("RunningService", "getServiceInfo returned null for: " + service.service); return false; } } catch (RemoteException e) { } si.mDisplayLabel = makeLabel(pm, si.mRunningService.service.getClassName(), si.mServiceInfo); mLabel = mDisplayLabel != null ? mDisplayLabel.toString() : null; si.mPackageInfo = si.mServiceInfo.applicationInfo; mServices.put(service.service, si); } si.mCurSeq = mCurSeq; si.mRunningService = service; long activeSince = service.restarting == 0 ? service.activeSince : -1; if (si.mActiveSince != activeSince) { si.mActiveSince = activeSince; changed = true; } if (service.clientPackage != null && service.clientLabel != 0) { if (si.mShownAsStarted) { si.mShownAsStarted = false; changed = true; } try { Resources clientr = pm.getResourcesForApplication(service.clientPackage); String label = clientr.getString(service.clientLabel); si.mDescription = context.getResources().getString(R.string.service_client_name, label); } catch (PackageManager.NameNotFoundException e) { si.mDescription = null; } } else { if (!si.mShownAsStarted) { si.mShownAsStarted = true; changed = true; } si.mDescription = context.getResources().getString(R.string.service_started_by_app); } return changed; }
/** * Return the user handle of the application that created this PendingIntent, that is the user * under which you will actually be sending the Intent. The returned UserHandle is supplied by the * system, so that an application can not spoof its user. See {@link * android.os.Process#myUserHandle() Process.myUserHandle()} for more explanation of user handles. * * <p class="note">Be careful about how you use this. All this tells you is who created the * PendingIntent. It does <strong>not</strong> tell you who handed the PendingIntent to you: that * is, PendingIntent objects are intended to be passed between applications, so the PendingIntent * you receive from an application could actually be one it received from another application, * meaning the result you get here will identify the original application. Because of this, you * should only use this information to identify who you expect to be interacting with through a * {@link #send} call, not who gave you the PendingIntent. * * @return The user handle of the PendingIntent, or null if there is none associated with it. */ @Nullable public UserHandle getCreatorUserHandle() { try { int uid = ActivityManagerNative.getDefault().getUidForIntentSender(mTarget); return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null; } catch (RemoteException e) { // Should never happen. return null; } }
/** * Convenience function to identify a job uniquely without pulling all the data that {@link * #toString()} returns. */ public String toShortString() { StringBuilder sb = new StringBuilder(); sb.append(Integer.toHexString(System.identityHashCode(this))); sb.append(" #"); UserHandle.formatUid(sb, callingUid); sb.append("/"); sb.append(job.getId()); sb.append(' '); sb.append(batteryName); return sb.toString(); }
@Override public boolean equals(Object other) { if (!(other instanceof UserHandleCompat)) { return false; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { return mUser.equals(((UserHandleCompat) other).mUser); } else { return true; } }
@Override public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) { // Override the fragment title for Wallpaper settings int titleRes = pref.getTitleRes(); if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) { titleRes = R.string.wallpaper_settings_fragment_title; } else if (pref.getFragment().equals(OwnerInfoSettings.class.getName()) && UserHandle.myUserId() != UserHandle.USER_OWNER) { titleRes = R.string.user_info_settings_title; } startPreferencePanel(pref.getFragment(), pref.getExtras(), titleRes, pref.getTitle(), null, 0); return true; }
private RunningState(Context context) { mApplicationContext = context.getApplicationContext(); mAm = (ActivityManager) mApplicationContext.getSystemService(Context.ACTIVITY_SERVICE); mPm = mApplicationContext.getPackageManager(); mUm = (UserManager) mApplicationContext.getSystemService(Context.USER_SERVICE); mMyUserId = UserHandle.myUserId(); mHideManagedProfiles = mMyUserId != UserHandle.USER_OWNER; mResumed = false; mBackgroundThread = new HandlerThread("RunningState:Background"); mBackgroundThread.start(); mBackgroundHandler = new BackgroundHandler(mBackgroundThread.getLooper()); mUmBroadcastReceiver.register(mApplicationContext); }
@Override public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) { if (!hasPermission(callingPackage)) { return null; } final int userId = UserHandle.getCallingUserId(); final long token = Binder.clearCallingIdentity(); try { return UsageStatsService.this.queryEvents(userId, beginTime, endTime); } finally { Binder.restoreCallingIdentity(token); } }
void handleShowAppErrorUi(Message msg) { AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj; boolean showBackground = Settings.Secure.getInt( mContext.getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; synchronized (mService) { ProcessRecord proc = data.proc; AppErrorResult res = data.result; if (proc != null && proc.crashDialog != null) { Slog.e(TAG, "App already has crash dialog: " + proc); if (res != null) { res.set(AppErrorDialog.ALREADY_SHOWING); } return; } boolean isBackground = (UserHandle.getAppId(proc.uid) >= Process.FIRST_APPLICATION_UID && proc.pid != MY_PID); for (int userId : mService.mUserController.getCurrentProfileIdsLocked()) { isBackground &= (proc.userId != userId); } if (isBackground && !showBackground) { Slog.w(TAG, "Skipping crash dialog of " + proc + ": background"); if (res != null) { res.set(AppErrorDialog.BACKGROUND_USER); } return; } final boolean crashSilenced = mAppsNotReportingCrashes != null && mAppsNotReportingCrashes.contains(proc.info.packageName); if (mService.canShowErrorDialogs() && !crashSilenced) { proc.crashDialog = new AppErrorDialog(mContext, mService, data); } else { // The device is asleep, so just pretend that the user // saw a crash dialog and hit "force quit". if (res != null) { res.set(AppErrorDialog.CANT_SHOW); } } } // If we've created a crash dialog, show it without the lock held if (data.proc.crashDialog != null) { data.proc.crashDialog.show(); } }
/** * Get an AccessibilityManager instance (create one if necessary). * * @param context Context in which this manager operates. * @hide */ public static AccessibilityManager getInstance(Context context) { synchronized (sInstanceSync) { if (sInstance == null) { final int userId; if (Binder.getCallingUid() == Process.SYSTEM_UID || context.checkCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS) == PackageManager.PERMISSION_GRANTED || context.checkCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL) == PackageManager.PERMISSION_GRANTED) { userId = UserHandle.USER_CURRENT; } else { userId = UserHandle.myUserId(); } sInstance = new AccessibilityManager(context, null, userId); } } return sInstance; }
private CharSequence getDomainsSummary(String packageName) { // If the user has explicitly said "no" for this package, that's the // string we should show. int domainStatus = mPm.getIntentVerificationStatus(packageName, UserHandle.myUserId()); if (domainStatus == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) { return mContext.getString(R.string.domain_urls_summary_none); } // Otherwise, ask package manager for the domains for this package, // and show the first one (or none if there aren't any). ArraySet<String> result = Utils.getHandledDomains(mPm, packageName); if (result.size() == 0) { return mContext.getString(R.string.domain_urls_summary_none); } else if (result.size() == 1) { return mContext.getString(R.string.domain_urls_summary_one, result.valueAt(0)); } else { return mContext.getString(R.string.domain_urls_summary_some, result.valueAt(0)); } }
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == INSTALLED_APP_DETAILS && mCurrentPkgName != null) { if (mListType == LIST_TYPE_NOTIFICATION) { mApplications.mExtraInfoBridge.forceUpdate(mCurrentPkgName, mCurrentUid); } else if (mListType == LIST_TYPE_HIGH_POWER || mListType == LIST_TYPE_OVERLAY || mListType == LIST_TYPE_WRITE_SETTINGS) { if (mFinishAfterDialog) { getActivity().onBackPressed(); } else { mApplications.mExtraInfoBridge.forceUpdate(mCurrentPkgName, mCurrentUid); } } else { mApplicationsState.requestSize(mCurrentPkgName, UserHandle.getUserId(mCurrentUid)); } } }
@Override public Set<X509Certificate> getCertificates() { // TODO: loading all of these is wasteful, we should instead use a keystore style API. synchronized (sLock) { if (sSystemCerts != null) { return sSystemCerts; } CertificateFactory certFactory; try { certFactory = CertificateFactory.getInstance("X.509"); } catch (CertificateException e) { throw new RuntimeException("Failed to obtain X.509 CertificateFactory", e); } final String ANDROID_ROOT = System.getenv("ANDROID_ROOT"); final File systemCaDir = new File(ANDROID_ROOT + "/etc/security/cacerts"); final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); final File userRemovedCaDir = new File(configDir, "cacerts-removed"); // Sanity check if (!systemCaDir.isDirectory()) { throw new AssertionError(systemCaDir + " is not a directory"); } Set<X509Certificate> systemCerts = new ArraySet<X509Certificate>(); for (String caFile : systemCaDir.list()) { // Skip any CAs in the user's deleted directory. if (new File(userRemovedCaDir, caFile).exists()) { continue; } InputStream is = null; try { is = new BufferedInputStream(new FileInputStream(new File(systemCaDir, caFile))); systemCerts.add((X509Certificate) certFactory.generateCertificate(is)); } catch (CertificateException | IOException e) { // Don't rethrow to be consistent with conscrypt's cert loading code. continue; } finally { IoUtils.closeQuietly(is); } } sSystemCerts = systemCerts; return sSystemCerts; } }
@Override public ParceledListSlice<UsageStats> queryUsageStats( int bucketType, long beginTime, long endTime, String callingPackage) { if (!hasPermission(callingPackage)) { return null; } final int userId = UserHandle.getCallingUserId(); final long token = Binder.clearCallingIdentity(); try { final List<UsageStats> results = UsageStatsService.this.queryUsageStats(userId, bucketType, beginTime, endTime); if (results != null) { return new ParceledListSlice<>(results); } } finally { Binder.restoreCallingIdentity(token); } return null; }
private void update(Set<Integer> users, Map<Integer, Boolean> apps, boolean add) { List<Integer> network = new ArrayList<Integer>(); List<Integer> system = new ArrayList<Integer>(); for (Entry<Integer, Boolean> app : apps.entrySet()) { List<Integer> list = app.getValue() ? system : network; for (int user : users) { list.add(UserHandle.getUid(user, app.getKey())); } } try { if (add) { mNetd.setPermission("NETWORK", toIntArray(network)); mNetd.setPermission("SYSTEM", toIntArray(system)); } else { mNetd.clearPermission(toIntArray(network)); mNetd.clearPermission(toIntArray(system)); } } catch (RemoteException e) { loge("Exception when updating permissions: " + e); } }
public String getSavedNetworkSummary() { if (mConfig != null) { PackageManager pm = mContext.getPackageManager(); String systemName = pm.getNameForUid(android.os.Process.SYSTEM_UID); int userId = UserHandle.getUserId(mConfig.creatorUid); ApplicationInfo appInfo = null; if (mConfig.creatorName != null && mConfig.creatorName.equals(systemName)) { appInfo = mContext.getApplicationInfo(); } else { try { IPackageManager ipm = AppGlobals.getPackageManager(); appInfo = ipm.getApplicationInfo(mConfig.creatorName, 0 /* flags */, userId); } catch (RemoteException rex) { } } if (appInfo != null && !appInfo.packageName.equals(mContext.getString(R.string.settings_package)) && !appInfo.packageName.equals(mContext.getString(R.string.certinstaller_package))) { return mContext.getString(R.string.saved_network, appInfo.loadLabel(pm)); } } return ""; }
@Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); mHandler = new MyHandler(this); mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); addPreferencesFromResource(R.xml.device_info_status); mBatteryLevel = findPreference(KEY_BATTERY_LEVEL); mBatteryStatus = findPreference(KEY_BATTERY_STATUS); mRes = getResources(); sUnknown = mRes.getString(R.string.device_info_default); if (UserHandle.myUserId() == UserHandle.USER_OWNER) { mPhone = PhoneFactory.getDefaultPhone(); } // Note - missing in zaku build, be careful later... mSignalStrength = findPreference(KEY_SIGNAL_STRENGTH); mUptime = findPreference("up_time"); if (mPhone == null || Utils.isWifiOnly(getApplicationContext())) { for (String key : PHONE_RELATED_ENTRIES) { removePreferenceFromScreen(key); } } else { // NOTE "imei" is the "Device ID" since it represents // the IMEI in GSM and the MEID in CDMA if (mPhone.getPhoneName().equals("CDMA")) { setSummaryText(KEY_MEID_NUMBER, mPhone.getMeid()); setSummaryText(KEY_MIN_NUMBER, mPhone.getCdmaMin()); if (getResources().getBoolean(R.bool.config_msid_enable)) { findPreference(KEY_MIN_NUMBER).setTitle(R.string.status_msid_number); } setSummaryText(KEY_PRL_VERSION, mPhone.getCdmaPrlVersion()); removePreferenceFromScreen(KEY_IMEI_SV); if (mPhone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) { // Show ICC ID and IMEI for LTE device setSummaryText(KEY_ICC_ID, mPhone.getIccSerialNumber()); setSummaryText(KEY_IMEI, mPhone.getImei()); } else { // device is not GSM/UMTS, do not display GSM/UMTS features // check Null in case no specified preference in overlay xml removePreferenceFromScreen(KEY_IMEI); removePreferenceFromScreen(KEY_ICC_ID); } } else { setSummaryText(KEY_IMEI, mPhone.getDeviceId()); setSummaryText( KEY_IMEI_SV, ((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).getDeviceSoftwareVersion()); // device is not CDMA, do not display CDMA features // check Null in case no specified preference in overlay xml removePreferenceFromScreen(KEY_PRL_VERSION); removePreferenceFromScreen(KEY_MEID_NUMBER); removePreferenceFromScreen(KEY_MIN_NUMBER); removePreferenceFromScreen(KEY_ICC_ID); // only show area info when SIM country is Brazil if ("br".equals(mTelephonyManager.getSimCountryIso())) { mShowLatestAreaInfo = true; } } String rawNumber = mPhone.getLine1Number(); // may be null or empty String formattedNumber = null; if (!TextUtils.isEmpty(rawNumber)) { formattedNumber = PhoneNumberUtils.formatNumber(rawNumber); } // If formattedNumber is null or empty, it'll display as "Unknown". setSummaryText(KEY_PHONE_NUMBER, formattedNumber); mPhoneStateReceiver = new PhoneStateIntentReceiver(this, mHandler); mPhoneStateReceiver.notifySignalStrength(EVENT_SIGNAL_STRENGTH_CHANGED); mPhoneStateReceiver.notifyServiceState(EVENT_SERVICE_STATE_CHANGED); if (!mShowLatestAreaInfo) { removePreferenceFromScreen(KEY_LATEST_AREA_INFO); } } setWimaxStatus(); setWifiStatus(); setBtStatus(); setIpAddressStatus(); String serial = Build.SERIAL; if (serial != null && !serial.equals("")) { setSummaryText(KEY_SERIAL_NUMBER, serial); } else { removePreferenceFromScreen(KEY_SERIAL_NUMBER); } }
private void updateHeaderList(List<Header> target) { final boolean showDev = mDevelopmentPreferences.getBoolean( DevelopmentSettings.PREF_SHOW, android.os.Build.TYPE.equals("eng") || android.os.Build.TYPE.equals("userdebug")); int i = 0; mHeaderIndexMap.clear(); while (i < target.size()) { Header header = target.get(i); // Ids are integers, so downcasting int id = (int) header.id; if (id == R.id.operator_settings || id == R.id.manufacturer_settings || id == R.id.advanced_settings || id == R.id.hybrid_settings) { Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header); } else if (id == R.id.launcher_settings) { Intent launcherIntent = new Intent(Intent.ACTION_MAIN); launcherIntent.addCategory(Intent.CATEGORY_HOME); launcherIntent.addCategory(Intent.CATEGORY_DEFAULT); Intent launcherPreferencesIntent = new Intent(Intent.ACTION_MAIN); launcherPreferencesIntent.addCategory("com.cyanogenmod.category.LAUNCHER_PREFERENCES"); ActivityInfo defaultLauncher = getPackageManager() .resolveActivity(launcherIntent, PackageManager.MATCH_DEFAULT_ONLY) .activityInfo; launcherPreferencesIntent.setPackage(defaultLauncher.packageName); ResolveInfo launcherPreferences = getPackageManager().resolveActivity(launcherPreferencesIntent, 0); if (launcherPreferences != null) { header.intent = new Intent() .setClassName( launcherPreferences.activityInfo.packageName, launcherPreferences.activityInfo.name); } else { target.remove(header); } } else if (id == R.id.wifi_settings) { // Remove WiFi Settings if WiFi service is not available. if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) { target.remove(i); } } else if (id == R.id.bluetooth_settings) { // Remove Bluetooth Settings if Bluetooth service is not available. if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) { target.remove(i); } } else if (id == R.id.data_usage_settings) { // Remove data usage when kernel module not enabled final INetworkManagementService netManager = INetworkManagementService.Stub.asInterface( ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); try { if (!netManager.isBandwidthControlEnabled()) { target.remove(i); } } catch (RemoteException e) { // ignored } } else if (id == R.id.account_settings) { int headerIndex = i + 1; i = insertAccountsHeaders(target, headerIndex); } else if (id == R.id.user_settings) { if (!UserHandle.MU_ENABLED || !UserManager.supportsMultipleUsers() || Utils.isMonkeyRunning()) { target.remove(i); } } if (target.get(i) == header && UserHandle.MU_ENABLED && UserHandle.myUserId() != 0 && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) { target.remove(i); } // Increment if the current one wasn't removed by the Utils code. if (target.get(i) == header) { // Hold on to the first header, when we need to reset to the top-level if (mFirstHeader == null && HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) { mFirstHeader = header; } mHeaderIndexMap.put(id, i); i++; } } }
@Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { if (preference.getKey().equals(KEY_FIRMWARE_VERSION)) { System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); mHits[mHits.length - 1] = SystemClock.uptimeMillis(); if (mHits[0] >= (SystemClock.uptimeMillis() - 500)) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName("android", com.android.internal.app.PlatLogoActivity.class.getName()); try { startActivity(intent); } catch (Exception e) { Log.e(LOG_TAG, "Unable to start activity " + intent.toString()); } } } else if (preference.getKey().equals(KEY_BUILD_NUMBER)) { // Only allow the owner of the device to turn on dev and performance options if (UserHandle.myUserId() == UserHandle.USER_OWNER) { if (mDevHitCountdown > 0) { mDevHitCountdown--; if (mDevHitCountdown == 0) { getActivity() .getSharedPreferences(DevelopmentSettings.PREF_FILE, Context.MODE_PRIVATE) .edit() .putBoolean(DevelopmentSettings.PREF_SHOW, true) .apply(); if (mDevHitToast != null) { mDevHitToast.cancel(); } mDevHitToast = Toast.makeText(getActivity(), R.string.show_dev_on, Toast.LENGTH_LONG); mDevHitToast.show(); } else if (mDevHitCountdown > 0 && mDevHitCountdown < (TAPS_TO_BE_A_DEVELOPER - 2)) { if (mDevHitToast != null) { mDevHitToast.cancel(); } mDevHitToast = Toast.makeText( getActivity(), getResources() .getQuantityString( R.plurals.show_dev_countdown, mDevHitCountdown, mDevHitCountdown), Toast.LENGTH_SHORT); mDevHitToast.show(); } } else if (mDevHitCountdown < 0) { if (mDevHitToast != null) { mDevHitToast.cancel(); } mDevHitToast = Toast.makeText(getActivity(), R.string.show_dev_already, Toast.LENGTH_LONG); mDevHitToast.show(); } } } else if (preference.getKey().equals(KEY_MOD_VERSION)) { System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); mHits[mHits.length - 1] = SystemClock.uptimeMillis(); if (mHits[0] >= (SystemClock.uptimeMillis() - 500)) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.putExtra("is_cid", true); intent.setClassName("android", com.android.internal.app.PlatLogoActivity.class.getName()); try { startActivity(intent); } catch (Exception e) { Log.e(LOG_TAG, "Unable to start activity " + intent.toString()); } } } return super.onPreferenceTreeClick(preferenceScreen, preference); }
@Override public void onCreate(Bundle icicle) { super.onCreate(icicle); addPreferencesFromResource(R.xml.device_info_settings); setStringSummary(KEY_FIRMWARE_VERSION, Build.VERSION.RELEASE); findPreference(KEY_FIRMWARE_VERSION).setEnabled(true); setValueSummary(KEY_BASEBAND_VERSION, "gsm.version.baseband"); setStringSummary(KEY_DEVICE_MODEL, Build.MODEL + getMsvSuffix()); setValueSummary(KEY_EQUIPMENT_ID, PROPERTY_EQUIPMENT_ID); setStringSummary(KEY_DEVICE_MODEL, Build.MODEL); setStringSummary(KEY_BUILD_NUMBER, Build.DISPLAY); findPreference(KEY_BUILD_NUMBER).setEnabled(true); findPreference(KEY_KERNEL_VERSION).setSummary(getFormattedKernelVersion()); setValueSummary(KEY_MOD_VERSION, "ro.cm.version"); findPreference(KEY_MOD_VERSION).setEnabled(true); setValueSummary(KEY_MOD_BUILD_DATE, "ro.build.date"); if (!SELinux.isSELinuxEnabled()) { String status = getResources().getString(R.string.selinux_status_disabled); setStringSummary(KEY_SELINUX_STATUS, status); } else if (!SELinux.isSELinuxEnforced()) { String status = getResources().getString(R.string.selinux_status_permissive); setStringSummary(KEY_SELINUX_STATUS, status); } findPreference(KEY_SELINUX_STATUS).setEnabled(true); if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { findPreference(KEY_STATUS) .getIntent() .setClassName("com.android.settings", "com.android.settings.deviceinfo.msim.MSimStatus"); } // Remove selinux information if property is not present removePreferenceIfPropertyMissing( getPreferenceScreen(), KEY_SELINUX_STATUS, PROPERTY_SELINUX_STATUS); String cpuInfo = getCPUInfo(); String memInfo = getMemInfo(); // Only the owner should see the Updater settings, if it exists if (UserHandle.myUserId() == UserHandle.USER_OWNER) { removePreferenceIfPackageNotInstalled(findPreference(KEY_CM_UPDATES)); } else { getPreferenceScreen().removePreference(findPreference(KEY_CM_UPDATES)); } if (cpuInfo != null) { setStringSummary(KEY_DEVICE_CPU, cpuInfo); } else { getPreferenceScreen().removePreference(findPreference(KEY_DEVICE_CPU)); } if (memInfo != null) { setStringSummary(KEY_DEVICE_MEMORY, memInfo); } else { getPreferenceScreen().removePreference(findPreference(KEY_DEVICE_MEMORY)); } // Remove Safety information preference if PROPERTY_URL_SAFETYLEGAL is not set removePreferenceIfPropertyMissing( getPreferenceScreen(), "safetylegal", PROPERTY_URL_SAFETYLEGAL); // Remove Equipment id preference if FCC ID is not set by RIL removePreferenceIfPropertyMissing( getPreferenceScreen(), KEY_EQUIPMENT_ID, PROPERTY_EQUIPMENT_ID); // Remove Baseband version if wifi-only device if (Utils.isWifiOnly(getActivity()) || (MSimTelephonyManager.getDefault().isMultiSimEnabled())) { getPreferenceScreen().removePreference(findPreference(KEY_BASEBAND_VERSION)); } /* * Settings is a generic app and should not contain any device-specific * info. */ final Activity act = getActivity(); // These are contained in the "container" preference group PreferenceGroup parentPreference = (PreferenceGroup) findPreference(KEY_CONTAINER); Utils.updatePreferenceToSpecificActivityOrRemove( act, parentPreference, KEY_TERMS, Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY); Utils.updatePreferenceToSpecificActivityOrRemove( act, parentPreference, KEY_LICENSE, Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY); Utils.updatePreferenceToSpecificActivityOrRemove( act, parentPreference, KEY_COPYRIGHT, Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY); Utils.updatePreferenceToSpecificActivityOrRemove( act, parentPreference, KEY_TEAM, Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY); // These are contained by the root preference screen parentPreference = getPreferenceScreen(); if (UserHandle.myUserId() == UserHandle.USER_OWNER) { Utils.updatePreferenceToSpecificActivityOrRemove( act, parentPreference, KEY_SYSTEM_UPDATE_SETTINGS, Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY); /* Make sure the activity is provided by who we want... */ if (findPreference(KEY_SYSTEM_UPDATE_SETTINGS) != null) removePreferenceIfPackageNotInstalled(findPreference(KEY_SYSTEM_UPDATE_SETTINGS)); } else { // Remove for secondary users removePreference(KEY_SYSTEM_UPDATE_SETTINGS); } Utils.updatePreferenceToSpecificActivityOrRemove( act, parentPreference, KEY_CONTRIBUTORS, Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY); // Read platform settings for additional system update setting removePreferenceIfBoolFalse( KEY_UPDATE_SETTING, R.bool.config_additional_system_update_setting_enable); // Remove regulatory information if not enabled. removePreferenceIfBoolFalse(KEY_REGULATORY_INFO, R.bool.config_show_regulatory_info); }
@Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { if (preference.getKey().equals(KEY_FIRMWARE_VERSION)) { System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); mHits[mHits.length - 1] = SystemClock.uptimeMillis(); if (mHits[0] >= (SystemClock.uptimeMillis() - 500)) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName("android", com.android.internal.app.PlatLogoActivity.class.getName()); try { startActivity(intent); } catch (Exception e) { Log.e(LOG_TAG, "Unable to start activity " + intent.toString()); } } } else if (preference.getKey().equals(KEY_BUILD_NUMBER)) { // Don't enable developer options for secondary users. if (UserHandle.myUserId() != UserHandle.USER_OWNER) return true; if (mDevHitCountdown > 0) { mDevHitCountdown--; if (mDevHitCountdown == 0) { getActivity() .getSharedPreferences(DevelopmentSettings.PREF_FILE, Context.MODE_PRIVATE) .edit() .putBoolean(DevelopmentSettings.PREF_SHOW, true) .apply(); if (mDevHitToast != null) { mDevHitToast.cancel(); } mDevHitToast = Toast.makeText(getActivity(), R.string.show_dev_on, Toast.LENGTH_LONG); mDevHitToast.show(); } else if (mDevHitCountdown > 0 && mDevHitCountdown < (TAPS_TO_BE_A_DEVELOPER - 2)) { if (mDevHitToast != null) { mDevHitToast.cancel(); } mDevHitToast = Toast.makeText( getActivity(), getResources() .getQuantityString( R.plurals.show_dev_countdown, mDevHitCountdown, mDevHitCountdown), Toast.LENGTH_SHORT); mDevHitToast.show(); } } else if (mDevHitCountdown < 0) { if (mDevHitToast != null) { mDevHitToast.cancel(); } mDevHitToast = Toast.makeText(getActivity(), R.string.show_dev_already, Toast.LENGTH_LONG); mDevHitToast.show(); } } else if (preference.getKey().equals(KEY_MOD_VERSION)) { System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); mHits[mHits.length - 1] = SystemClock.uptimeMillis(); if (mHits[0] >= (SystemClock.uptimeMillis() - 500)) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.putExtra("is_cid", true); intent.setClassName("android", com.android.internal.app.PlatLogoActivity.class.getName()); try { startActivity(intent); } catch (Exception e) { Log.e(LOG_TAG, "Unable to start activity " + intent.toString()); } } } else if (preference.getKey().equals(KEY_SELINUX_STATUS)) { System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); mHits[mHits.length - 1] = SystemClock.uptimeMillis(); if (mHits[0] >= (SystemClock.uptimeMillis() - 500)) { if (SELinux.isSELinuxEnabled()) { if (!SELinux.isSELinuxEnforced()) { /* Display the warning dialog */ AlertDialog alertDialog = new AlertDialog.Builder(getActivity()).create(); alertDialog.setTitle(R.string.selinux_enable_title); alertDialog.setMessage(getResources().getString(R.string.selinux_enable_warning)); alertDialog.setButton( DialogInterface.BUTTON_POSITIVE, getResources().getString(com.android.internal.R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { SELinux.setSELinuxEnforce(true); String status = getResources().getString(R.string.selinux_status_enforcing); setStringSummary(KEY_SELINUX_STATUS, status); } }); alertDialog.setButton( DialogInterface.BUTTON_NEGATIVE, getResources().getString(com.android.internal.R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) {} }); alertDialog.setOnCancelListener( new DialogInterface.OnCancelListener() { public void onCancel(DialogInterface dialog) {} }); alertDialog.show(); } else { SELinux.setSELinuxEnforce(false); } } if (!SELinux.isSELinuxEnabled()) { String status = getResources().getString(R.string.selinux_status_disabled); setStringSummary(KEY_SELINUX_STATUS, status); } else if (!SELinux.isSELinuxEnforced()) { String status = getResources().getString(R.string.selinux_status_permissive); setStringSummary(KEY_SELINUX_STATUS, status); } else if (SELinux.isSELinuxEnforced()) { String status = getResources().getString(R.string.selinux_status_enforcing); setStringSummary(KEY_SELINUX_STATUS, status); } } } return super.onPreferenceTreeClick(preferenceScreen, preference); }
final void processNextBroadcast(boolean fromMsg) { synchronized (mService) { BroadcastRecord r; if (DEBUG_BROADCAST) Slog.v( TAG, "processNextBroadcast [" + mQueueName + "]: " + mParallelBroadcasts.size() + " broadcasts, " + mOrderedBroadcasts.size() + " ordered broadcasts"); mService.updateCpuStats(); if (fromMsg) { mBroadcastsScheduled = false; } // First, deliver any non-serialized broadcasts right away. while (mParallelBroadcasts.size() > 0) { r = mParallelBroadcasts.remove(0); r.dispatchTime = SystemClock.uptimeMillis(); r.dispatchClockTime = System.currentTimeMillis(); mCurrentBroadcast = r; final int N = r.receivers.size(); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast [" + mQueueName + "] " + r); for (int i = 0; i < N; i++) { Object target = r.receivers.get(i); if (DEBUG_BROADCAST) Slog.v( TAG, "Delivering non-ordered on [" + mQueueName + "] to registered " + target + ": " + r); deliverToRegisteredReceiverLocked(r, (BroadcastFilter) target, false); } addBroadcastToHistoryLocked(r); mCurrentBroadcast = null; if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast [" + mQueueName + "] " + r); } // Now take care of the next serialized one... // If we are waiting for a process to come up to handle the next // broadcast, then do nothing at this point. Just in case, we // check that the process we're waiting for still exists. if (mPendingBroadcast != null) { if (DEBUG_BROADCAST_LIGHT) { Slog.v( TAG, "processNextBroadcast [" + mQueueName + "]: waiting for " + mPendingBroadcast.curApp); } boolean isDead; synchronized (mService.mPidsSelfLocked) { isDead = (mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null); } if (!isDead) { // It's still alive, so keep waiting return; } else { Slog.w( TAG, "pending app [" + mQueueName + "]" + mPendingBroadcast.curApp + " died before responding to broadcast"); mPendingBroadcast.state = BroadcastRecord.IDLE; mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex; mPendingBroadcast = null; } } boolean looped = false; do { if (mOrderedBroadcasts.size() == 0) { // No more broadcasts pending, so all done! mService.scheduleAppGcsLocked(); if (looped) { // If we had finished the last ordered broadcast, then // make sure all processes have correct oom and sched // adjustments. mService.updateOomAdjLocked(); } return; } r = mOrderedBroadcasts.get(0); mCurrentBroadcast = r; boolean forceReceive = false; // Ensure that even if something goes awry with the timeout // detection, we catch "hung" broadcasts here, discard them, // and continue to make progress. // // This is only done if the system is ready so that PRE_BOOT_COMPLETED // receivers don't get executed with timeouts. They're intended for // one time heavy lifting after system upgrades and can take // significant amounts of time. int numReceivers = (r.receivers != null) ? r.receivers.size() : 0; if (mService.mProcessesReady && r.dispatchTime > 0) { long now = SystemClock.uptimeMillis(); if ((numReceivers > 0) && (now > r.dispatchTime + (2 * mTimeoutPeriod * numReceivers))) { Slog.w( TAG, "Hung broadcast [" + mQueueName + "] discarded after timeout failure:" + " now=" + now + " dispatchTime=" + r.dispatchTime + " startTime=" + r.receiverTime + " intent=" + r.intent + " numReceivers=" + numReceivers + " nextReceiver=" + r.nextReceiver + " state=" + r.state); broadcastTimeoutLocked(false); // forcibly finish this broadcast forceReceive = true; r.state = BroadcastRecord.IDLE; } } if (r.state != BroadcastRecord.IDLE) { if (DEBUG_BROADCAST) Slog.d( TAG, "processNextBroadcast(" + mQueueName + ") called when not idle (state=" + r.state + ")"); return; } if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) { // No more receivers for this broadcast! Send the final // result if requested... if (r.resultTo != null) { try { if (DEBUG_BROADCAST) { int seq = r.intent.getIntExtra("seq", -1); Slog.i( TAG, "Finishing broadcast [" + mQueueName + "] " + r.intent.getAction() + " seq=" + seq + " app=" + r.callerApp); } performReceiveLocked( r.callerApp, r.resultTo, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, false, false, r.userId); // Set this to null so that the reference // (local and remote) isnt kept in the mBroadcastHistory. r.resultTo = null; } catch (RemoteException e) { Slog.w( TAG, "Failure [" + mQueueName + "] sending broadcast result of " + r.intent, e); } } if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG"); cancelBroadcastTimeoutLocked(); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast " + r); // ... and on to the next... addBroadcastToHistoryLocked(r); mOrderedBroadcasts.remove(0); mCurrentBroadcast = null; r = null; looped = true; continue; } } while (r == null); // Get the next receiver... int recIdx = r.nextReceiver++; // Keep track of when this receiver started, and make sure there // is a timeout message pending to kill it if need be. r.receiverTime = SystemClock.uptimeMillis(); if (recIdx == 0) { r.dispatchTime = r.receiverTime; r.dispatchClockTime = System.currentTimeMillis(); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast [" + mQueueName + "] " + r); } if (!mPendingBroadcastTimeoutMessage) { long timeoutTime = r.receiverTime + mTimeoutPeriod; if (DEBUG_BROADCAST) Slog.v( TAG, "Submitting BROADCAST_TIMEOUT_MSG [" + mQueueName + "] for " + r + " at " + timeoutTime); setBroadcastTimeoutLocked(timeoutTime); } Object nextReceiver = r.receivers.get(recIdx); if (nextReceiver instanceof BroadcastFilter) { // Simple case: this is a registered receiver who gets // a direct call. BroadcastFilter filter = (BroadcastFilter) nextReceiver; if (DEBUG_BROADCAST) Slog.v(TAG, "Delivering ordered [" + mQueueName + "] to registered " + filter + ": " + r); deliverToRegisteredReceiverLocked(r, filter, r.ordered); if (r.receiver == null || !r.ordered) { // The receiver has already finished, so schedule to // process the next one. if (DEBUG_BROADCAST) Slog.v( TAG, "Quick finishing [" + mQueueName + "]: ordered=" + r.ordered + " receiver=" + r.receiver); r.state = BroadcastRecord.IDLE; scheduleBroadcastsLocked(); } return; } // Hard case: need to instantiate the receiver, possibly // starting its application process to host it. ResolveInfo info = (ResolveInfo) nextReceiver; ComponentName component = new ComponentName(info.activityInfo.applicationInfo.packageName, info.activityInfo.name); boolean skip = false; int perm = mService.checkComponentPermission( info.activityInfo.permission, r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid, info.activityInfo.exported); if (perm != PackageManager.PERMISSION_GRANTED) { if (!info.activityInfo.exported) { Slog.w( TAG, "Permission Denial: broadcasting " + r.intent.toString() + " from " + r.callerPackage + " (pid=" + r.callingPid + ", uid=" + r.callingUid + ")" + " is not exported from uid " + info.activityInfo.applicationInfo.uid + " due to receiver " + component.flattenToShortString()); } else { Slog.w( TAG, "Permission Denial: broadcasting " + r.intent.toString() + " from " + r.callerPackage + " (pid=" + r.callingPid + ", uid=" + r.callingUid + ")" + " requires " + info.activityInfo.permission + " due to receiver " + component.flattenToShortString()); } skip = true; } if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID && r.requiredPermission != null) { try { perm = AppGlobals.getPackageManager() .checkPermission( r.requiredPermission, info.activityInfo.applicationInfo.packageName); } catch (RemoteException e) { perm = PackageManager.PERMISSION_DENIED; } if (perm != PackageManager.PERMISSION_GRANTED) { Slog.w( TAG, "Permission Denial: receiving " + r.intent + " to " + component.flattenToShortString() + " requires " + r.requiredPermission + " due to sender " + r.callerPackage + " (uid " + r.callingUid + ")"); skip = true; } } if (r.appOp != AppOpsManager.OP_NONE) { int mode = mService.mAppOpsService.checkOperation( r.appOp, info.activityInfo.applicationInfo.uid, info.activityInfo.packageName); if (mode != AppOpsManager.MODE_ALLOWED) { if (DEBUG_BROADCAST) Slog.v( TAG, "App op " + r.appOp + " not allowed for broadcast to uid " + info.activityInfo.applicationInfo.uid + " pkg " + info.activityInfo.packageName); skip = true; } } // MUTT if (mMuttFilter.hasAction(r.intent.getAction())) { Slog.v(TAG, "MUTT: whitelist broadcast " + r.intent.toString()); } else { if (mService.mBatteryStatsService.allowMutt( info.activityInfo.applicationInfo.uid, info.activityInfo.packageName) != 0) { Slog.w( TAG, "MUTT: skipping broadcasting " + r.intent.toString() + " from " + r.callerPackage + " (pid=" + r.callingPid + ", uid=" + r.callingUid + " to " + component.flattenToShortString() + ")"); skip = true; } } boolean isSingleton = false; try { isSingleton = mService.isSingleton( info.activityInfo.processName, info.activityInfo.applicationInfo, info.activityInfo.name, info.activityInfo.flags); } catch (SecurityException e) { Slog.w(TAG, e.getMessage()); skip = true; } if ((info.activityInfo.flags & ActivityInfo.FLAG_SINGLE_USER) != 0) { if (ActivityManager.checkUidPermission( android.Manifest.permission.INTERACT_ACROSS_USERS, info.activityInfo.applicationInfo.uid) != PackageManager.PERMISSION_GRANTED) { Slog.w( TAG, "Permission Denial: Receiver " + component.flattenToShortString() + " requests FLAG_SINGLE_USER, but app does not hold " + android.Manifest.permission.INTERACT_ACROSS_USERS); skip = true; } } if (r.curApp != null && r.curApp.crashing) { // If the target process is crashing, just skip it. if (DEBUG_BROADCAST) Slog.v( TAG, "Skipping deliver ordered [" + mQueueName + "] " + r + " to " + r.curApp + ": process crashing"); skip = true; } if (skip) { if (DEBUG_BROADCAST) Slog.v( TAG, "Skipping delivery of ordered [" + mQueueName + "] " + r + " for whatever reason"); r.receiver = null; r.curFilter = null; r.state = BroadcastRecord.IDLE; scheduleBroadcastsLocked(); return; } r.state = BroadcastRecord.APP_RECEIVE; String targetProcess = info.activityInfo.processName; r.curComponent = component; if (r.callingUid != Process.SYSTEM_UID && isSingleton) { info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0); } r.curReceiver = info.activityInfo; if (DEBUG_MU && r.callingUid > UserHandle.PER_USER_RANGE) { Slog.v( TAG_MU, "Updated broadcast record activity info for secondary user, " + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = " + info.activityInfo.applicationInfo.uid); } // Broadcast is being executed, its package can't be stopped. try { AppGlobals.getPackageManager() .setPackageStoppedState( r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid)); } catch (RemoteException e) { } catch (IllegalArgumentException e) { Slog.w( TAG, "Failed trying to unstop package " + r.curComponent.getPackageName() + ": " + e); } // Is this receiver's application already running? ProcessRecord app = mService.getProcessRecordLocked(targetProcess, info.activityInfo.applicationInfo.uid); if (app != null && app.thread != null) { try { app.addPackage(info.activityInfo.packageName); processCurBroadcastLocked(r, app); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when sending broadcast to " + r.curComponent, e); } catch (RuntimeException e) { Log.wtf(TAG, "Failed sending broadcast to " + r.curComponent + " with " + r.intent, e); // If some unexpected exception happened, just skip // this broadcast. At this point we are not in the call // from a client, so throwing an exception out from here // will crash the entire system instead of just whoever // sent the broadcast. logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); scheduleBroadcastsLocked(); // We need to reset the state if we failed to start the receiver. r.state = BroadcastRecord.IDLE; return; } // If a dead object exception was thrown -- fall through to // restart the application. } // Not running -- get it started, to be executed when the app comes up. if (DEBUG_BROADCAST) Slog.v( TAG, "Need to start app [" + mQueueName + "] " + targetProcess + " for broadcast " + r); if ((r.curApp = mService.startProcessLocked( targetProcess, info.activityInfo.applicationInfo, true, r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND, "broadcast", r.curComponent, (r.intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false)) == null) { // Ah, this recipient is unavailable. Finish it if necessary, // and mark the broadcast record as ready for the next. Slog.w( TAG, "Unable to launch app " + info.activityInfo.applicationInfo.packageName + "/" + info.activityInfo.applicationInfo.uid + " for broadcast " + r.intent + ": process is bad"); logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); scheduleBroadcastsLocked(); r.state = BroadcastRecord.IDLE; return; } mPendingBroadcast = r; mPendingBroadcastRecvIndex = recIdx; } }