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 "";
 }
Ejemplo n.º 25
0
  @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++;
      }
    }
  }
Ejemplo n.º 27
0
 @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;
    }
  }