Esempio n. 1
0
  /**
   * Creates a command set for commands operation.
   *
   * @param pid process id
   * @param uid user id
   * @param setName command set name
   * @param featureType feature type
   * @return result
   */
  public int createSetLocked(int pid, int uid, String setName, int featureType) {
    // TODO Auto-generated method stub

    int result = VoiceCommonState.SUCCESS;

    ProcessRecord processRecord = getProcessRecordLocked(pid, uid);
    ListenerRecord listenerRecord =
        processRecord == null ? null : processRecord.getListenerRecord(getFeatureName(featureType));

    if (listenerRecord == null) {
      // Check whether is illegal process from third party application
      // Maybe third application connect service without using
      // VoiceCommandManager
      result = VoiceCommonState.PROCESS_ILLEGAL;
    } else {

      if (setName.equals(listenerRecord.getSetName())) {
        // The setName already in used ,so don't need to ask swip
        // creating the set
        result = VoiceCommonState.SET_ALREADY_EXIST;
      } else {
        // Ask Swip whether the setName is created
        String swipSet =
            ProcessRecord.getSetNameForSwip(
                processRecord.getProcssName(),
                processRecord.getPid(),
                getFeatureName(featureType),
                setName);
        result = mSwip.createSetName(swipSet, featureType);
      }
    }

    return result;
  }
Esempio n. 2
0
  /**
   * Checks if the command set already exists.
   *
   * @param pid process id
   * @param uid user id
   * @param setName command set name
   * @param featureType feature type
   * @return result
   */
  public int isSetCreatedLocked(int pid, int uid, String setName, int featureType) {

    int result = VoiceCommonState.SUCCESS;

    ProcessRecord processRecord = getProcessRecordLocked(pid, uid);
    ListenerRecord listenerRecord =
        processRecord == null ? null : processRecord.getListenerRecord(getFeatureName(featureType));

    if (processRecord == null || listenerRecord == null) {
      // Check whether is illegal process from third party application
      // Maybe third application connect service without using
      // VoiceCommandManager
      result = VoiceCommonState.PROCESS_ILLEGAL;
    } else {
      // Ask swip to check whether the set is already created
      if (!setName.equals(listenerRecord.getSetName())) {
        // First check whether the set is already selected
        String swipSet =
            ProcessRecord.getSetNameForSwip(
                processRecord.getProcssName(),
                processRecord.getPid(),
                getFeatureName(featureType),
                setName);
        result = mSwip.isSetCreated(swipSet, featureType);
      }
    }

    return result;
  }
Esempio n. 3
0
  /**
   * Remove process record for voice extension service.
   *
   * @param pid process id
   * @param uid user id
   */
  public void removeProcessRecordLocked(int pid, int uid) {
    ProcessRecord record = mProcessRecords.get(pid);

    if (record != null && record.getUid() == uid) {
      mProcessRecords.remove(pid);
    }
  }
  /**
   * @param conf used to contact HBase and to run jobs against
   * @param cluster for which to process records.
   * @param processFileSubstring return rows where the process file path contains this string. If
   *     <code>null</code> or empty string, then no filtering is applied.
   * @return whether all job files for all processRecords were properly Printed.
   * @throws IOException
   */
  private boolean printProcessRecordsFromHBase(
      Configuration conf, String cluster, int maxCount, String processFileSubstring)
      throws IOException {
    ProcessRecordService processRecordService = new ProcessRecordService(conf);
    List<ProcessRecord> processRecords =
        processRecordService.getProcessRecords(cluster, maxCount, processFileSubstring);
    try {

      int jobFileCount = 0;

      System.out.println("ProcessRecords for " + cluster + ": " + processRecords.size());

      // Iterate over 0 based list in reverse order
      for (int j = processRecords.size() - 1; j >= 0; j--) {
        ProcessRecord processRecord = processRecords.get(j);

        // Print the whole thing.
        System.out.println(processRecord);
        jobFileCount += processRecord.getProcessedJobFiles();
      }
      System.out.println(
          "Printed "
              + processRecords.size()
              + " records with a total of "
              + jobFileCount
              + " files.");
    } finally {
      processRecordService.close();
    }

    return true;
  }
Esempio n. 5
0
  /**
   * The callback result of process dead.
   *
   * @param record process record
   */
  public void onProcessDiedLocked(ProcessRecord record) {

    if (mSwipOccupiedProcess == record) {
      mSwipOccupiedProcess = null;
    }
    removeProcessRecordLocked(record.getPid(), record.getUid());
  }
Esempio n. 6
0
  /**
   * Get the process record with the same pid & uid.
   *
   * @param pid process id
   * @param uid user id
   * @return process record
   */
  public ProcessRecord getProcessRecordLocked(int pid, int uid) {
    ProcessRecord record = mProcessRecords.get(pid);

    if (record != null && record.getUid() != uid) {
      record = null;
      // mProcessRecords.remove(pid);
    }
    return record;
  }
Esempio n. 7
0
  /**
   * Gets all command sets.
   *
   * @param pid process id
   * @param uid user id
   * @param featureType feature type
   * @return all command sets
   */
  public String[] getAllSetsLocked(int pid, int uid, int featureType) {

    String[] sets = null;
    ProcessRecord processRecord = getProcessRecordLocked(pid, uid);
    ListenerRecord listenerRecord =
        processRecord == null ? null : processRecord.getListenerRecord(getFeatureName(featureType));
    if (listenerRecord != null) {
      // Ask swip to get the sets of this process
      sets = mSwip.getAllSets(processRecord.getProcssName(), featureType);
    }
    return sets;
  }
  void handleShowAnrUi(Message msg) {
    Dialog d = null;
    synchronized (mService) {
      HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
      ProcessRecord proc = (ProcessRecord) data.get("app");
      if (proc != null && proc.anrDialog != null) {
        Slog.e(TAG, "App already has anr dialog: " + proc);
        MetricsLogger.action(
            mContext,
            MetricsProto.MetricsEvent.ACTION_APP_ANR,
            AppNotRespondingDialog.ALREADY_SHOWING);
        return;
      }

      Intent intent = new Intent("android.intent.action.ANR");
      if (!mService.mProcessesReady) {
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
      }
      mService.broadcastIntentLocked(
          null,
          null,
          intent,
          null,
          null,
          0,
          null,
          null,
          null,
          AppOpsManager.OP_NONE,
          null,
          false,
          false,
          MY_PID,
          Process.SYSTEM_UID,
          0 /* TODO: Verify */);

      if (mService.canShowErrorDialogs()) {
        d =
            new AppNotRespondingDialog(
                mService, mContext, proc, (ActivityRecord) data.get("activity"), msg.arg1 != 0);
        proc.anrDialog = d;
      } else {
        MetricsLogger.action(
            mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, AppNotRespondingDialog.CANT_SHOW);
        // Just kill the app if there is no dialog to be shown.
        mService.killAppAtUsersRequest(proc, null);
      }
    }
    // If we've created a crash dialog, show it without the lock held
    if (d != null) {
      d.show();
    }
  }
 private void makeAppNotRespondingLocked(
     ProcessRecord app, String activity, String shortMsg, String longMsg) {
   app.notResponding = true;
   app.notRespondingReport =
       generateProcessError(
           app,
           ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
           activity,
           shortMsg,
           longMsg,
           null);
   startAppProblemLocked(app);
   app.stopFreezingAllLocked();
 }
  void startAppProblemLocked(ProcessRecord app) {
    // If this app is not running under the current user, then we
    // can't give it a report button because that would require
    // launching the report UI under a different user.
    app.errorReportReceiver = null;

    for (int userId : mService.mUserController.getCurrentProfileIdsLocked()) {
      if (app.userId == userId) {
        app.errorReportReceiver =
            ApplicationErrorReport.getErrorReportReceiver(
                mContext, app.info.packageName, app.info.flags);
      }
    }
    mService.skipCurrentReceiverLocked(app);
  }
Esempio n. 11
0
  /**
   * Gets the current selected command set.
   *
   * @param pid process id
   * @param uid user id
   * @param featureType feature type
   * @return the current selected command set
   */
  public String getSetSelected(int pid, int uid, int featureType) {
    String setName = null;

    ProcessRecord processRecord = getProcessRecordLocked(pid, uid);
    ListenerRecord listenerRecord =
        processRecord == null ? null : processRecord.getListenerRecord(getFeatureName(featureType));

    if (listenerRecord != null) {
      // Check whether is illegal process from third party application
      // Maybe third application connect service without using
      // VoiceCommandManager
      setName = listenerRecord.getSetName();
    }

    return setName;
  }
 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();
   }
 }
Esempio n. 13
0
  /**
   * Get the process record with the same processName.
   *
   * @param processName process name
   * @return process record
   */
  public ProcessRecord getProcessRecordLocked(String processName) {
    ProcessRecord record = null;

    if (mSwipOccupiedProcess != null && mSwipOccupiedProcess.getProcssName().equals(processName)) {
      record = mSwipOccupiedProcess;
    } else {
      Iterator<Entry<Integer, ProcessRecord>> iterator = mProcessRecords.entrySet().iterator();
      while (iterator.hasNext()) {
        record = iterator.next().getValue();
        if (!record.getProcssName().equals(processName)) {
          record = null;
          continue;
        }
        break;
      }
    }
    return record;
  }
 private boolean makeAppCrashingLocked(
     ProcessRecord app,
     String shortMsg,
     String longMsg,
     String stackTrace,
     AppErrorDialog.Data data) {
   app.crashing = true;
   app.crashingReport =
       generateProcessError(
           app,
           ActivityManager.ProcessErrorStateInfo.CRASHED,
           null,
           shortMsg,
           longMsg,
           stackTrace);
   startAppProblemLocked(app);
   app.stopFreezingAllLocked();
   return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace, data);
 }
  private final void processCurBroadcastLocked(BroadcastRecord r, ProcessRecord app)
      throws RemoteException {
    if (DEBUG_BROADCAST) Slog.v(TAG, "Process cur broadcast " + r + " for app " + app);
    if (app.thread == null) {
      throw new RemoteException();
    }
    r.receiver = app.thread.asBinder();
    r.curApp = app;
    app.curReceiver = r;
    mService.updateLruProcessLocked(app, true);

    // Tell the application to launch this receiver.
    r.intent.setComponent(r.curComponent);

    boolean started = false;
    try {
      if (DEBUG_BROADCAST_LIGHT)
        Slog.v(TAG, "Delivering to component " + r.curComponent + ": " + r);
      mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
      app.thread.scheduleReceiver(
          new Intent(r.intent),
          r.curReceiver,
          mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
          r.resultCode,
          r.resultData,
          r.resultExtras,
          r.ordered,
          r.userId);
      if (DEBUG_BROADCAST) Slog.v(TAG, "Process cur broadcast " + r + " DELIVERED for app " + app);
      started = true;
    } finally {
      if (!started) {
        if (DEBUG_BROADCAST) Slog.v(TAG, "Process cur broadcast " + r + ": NOT STARTED!");
        r.receiver = null;
        r.curApp = null;
        app.curReceiver = null;
      }
    }
  }
Esempio n. 16
0
  /**
   * Switch occupied swip process record.
   *
   * @param processRecord process record
   * @param featureType feature type
   * @return result
   */
  public int switchSwipOccupiedProcessLocked(ProcessRecord processRecord, int featureType) {

    int result = VoiceCommonState.SUCCESS;

    ListenerRecord listenerRecord =
        processRecord == null ? null : processRecord.getListenerRecord(getFeatureName(featureType));

    if (processRecord == null || listenerRecord == null) {
      result = VoiceCommonState.PROCESS_ILLEGAL;
    } else {
      if (mSwipOccupiedProcess != null && processRecord != mSwipOccupiedProcess) {
        result = VoiceCommonState.MIC_OCCUPIED;
      } else {
        // (1)Switch process record
        mSwipOccupiedProcess = processRecord;
        // Means switch success , current mSwipOccupiedProcess can
        // access swip
        // (2)Switch listener record
        result = processRecord.switchSwipListenerRecord(listenerRecord);
      }
    }
    return result;
  }
  void scheduleAppCrashLocked(int uid, int initialPid, String packageName, String message) {
    ProcessRecord proc = null;

    // Figure out which process to kill.  We don't trust that initialPid
    // still has any relation to current pids, so must scan through the
    // list.

    synchronized (mService.mPidsSelfLocked) {
      for (int i = 0; i < mService.mPidsSelfLocked.size(); i++) {
        ProcessRecord p = mService.mPidsSelfLocked.valueAt(i);
        if (p.uid != uid) {
          continue;
        }
        if (p.pid == initialPid) {
          proc = p;
          break;
        }
        if (p.pkgList.containsKey(packageName)) {
          proc = p;
        }
      }
    }

    if (proc == null) {
      Slog.w(
          TAG,
          "crashApplication: nothing for uid="
              + uid
              + " initialPid="
              + initialPid
              + " packageName="
              + packageName);
      return;
    }

    proc.scheduleCrash(message);
  }
Esempio n. 18
0
  /**
   * Register record for application from voice service.
   *
   * @param pid process id
   * @param uid user id
   * @param listener a callback that receive asynchronous notification from swip
   * @param featureType feature type
   * @param commonState common state or main state
   * @param featureState feture state or sub state
   * @param handler FeatureManager instance
   * @return result
   */
  public int registerListenerLocked(
      int pid,
      int uid,
      Object listener,
      int featureType,
      int commonState,
      int featureState,
      FeatureManager handler) {

    int result = VoiceCommonState.SUCCESS;

    ProcessRecord processRecord = createProcessRecordLocked(pid, uid);
    String featureName = getFeatureName(featureType);
    if (processRecord == null) {
      result = VoiceCommonState.PROCESS_ILLEGAL;
    } else {

      ListenerRecord record = processRecord.getListenerRecord(featureName);

      if (record == null) {
        record = processRecord.createListenerRecord();
        try {
          ((IInterface) listener).asBinder().linkToDeath(processRecord, 0);
          processRecord.addListenerRecord(featureName, record);
        } catch (RemoteException ex) {
          result = VoiceCommonState.PROCESS_ILLEGAL;
        }
      } else {
        // This case only can be happened while service didn't
        // receive
        // the died notification.
        // We need to notify native if possible
        if (CommonManager.DEBUG) {
          Log.d(
              TAG,
              "Register listener old pid="
                  + processRecord.getPid()
                  + " old uid="
                  + processRecord.getUid()
                  + " old processName="
                  + processRecord.getProcssName());
        }
      }
      if (result == VoiceCommonState.SUCCESS) {
        record.init(listener, featureType, featureName, commonState, featureState, handler);
      }
    }

    return result;
  }
  private boolean handleAppCrashInActivityController(
      ProcessRecord r,
      ApplicationErrorReport.CrashInfo crashInfo,
      String shortMsg,
      String longMsg,
      String stackTrace,
      long timeMillis) {
    if (mService.mController == null) {
      return false;
    }

    try {
      String name = r != null ? r.processName : null;
      int pid = r != null ? r.pid : Binder.getCallingPid();
      int uid = r != null ? r.info.uid : Binder.getCallingUid();
      if (!mService.mController.appCrashed(
          name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
        if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
            && "Native crash".equals(crashInfo.exceptionClassName)) {
          Slog.w(TAG, "Skip killing native crashed app " + name + "(" + pid + ") during testing");
        } else {
          Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request");
          if (r != null) {
            if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) {
              r.kill("crash", true);
            }
          } else {
            // Huh.
            Process.killProcess(pid);
            ActivityManagerService.killProcessGroup(uid, pid);
          }
        }
        return true;
      }
    } catch (RemoteException e) {
      mService.mController = null;
      Watchdog.getInstance().setActivityController(null);
    }
    return false;
  }
Esempio n. 20
0
  /**
   * Selects a command set for setting up commands or command recognition operation.
   *
   * @param pid process id
   * @param uid user id
   * @param setName command set name
   * @param featureType feature type
   * @return result
   */
  public int selectSetLocked(int pid, int uid, String setName, int featureType) {

    int result = VoiceCommonState.SUCCESS;

    if (setName == null) {

      result = VoiceCommonState.SET_ILLEGAL;
      Log.e(TAG, "select Set fail, set name =" + setName);

    } else {

      ProcessRecord processRecord = getProcessRecordLocked(pid, uid);
      ListenerRecord listenerRecord =
          processRecord == null
              ? null
              : processRecord.getListenerRecord(getFeatureName(featureType));
      if (processRecord == null || listenerRecord == null) {
        // Check whether is illegal process from third party application
        // Maybe third application connect service without using
        // VoiceCommandManager
        result = VoiceCommonState.PROCESS_ILLEGAL;
      } else if (setName.equals(listenerRecord.getSetName())) {
        result = VoiceCommonState.SET_SELECTED;
      } else if (processRecord.isListenerOccupiedSwip(listenerRecord)) {
        // Current listenerRecord occupy the swip , can't switch set
        result = VoiceCommonState.MIC_OCCUPIED;
      } else {
        // Ask swip that is this set created
        String swipSet =
            ProcessRecord.getSetNameForSwip(
                processRecord.getProcssName(),
                processRecord.getPid(),
                getFeatureName(featureType),
                setName);
        result = mSwip.isSetCreated(swipSet, featureType);
        if (result == VoiceCommonState.SET_ALREADY_EXIST) {
          listenerRecord.setSetName(setName);
          // result = processRecord
          // .switchSwipListenerRecord(listenerRecord);
          result = VoiceCommonState.SUCCESS;
        }
      }
    }
    return result;
  }
 void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) {
   app.crashing = false;
   app.crashingReport = null;
   app.notResponding = false;
   app.notRespondingReport = null;
   if (app.anrDialog == fromDialog) {
     app.anrDialog = null;
   }
   if (app.waitDialog == fromDialog) {
     app.waitDialog = null;
   }
   if (app.pid > 0 && app.pid != MY_PID) {
     handleAppCrashLocked(
         app,
         "user-terminated" /*reason*/,
         null /*shortMsg*/,
         null /*longMsg*/,
         null /*stackTrace*/,
         null /*data*/);
     app.kill("user request after error", true);
   }
 }
Esempio n. 22
0
  /**
   * Deletes the command set.
   *
   * @param pid process id
   * @param uid user id
   * @param setName command set name
   * @param featureType feature type
   * @return result
   */
  public int deleteSetLocked(int pid, int uid, String setName, int featureType) {

    int result = VoiceCommonState.SUCCESS;

    ProcessRecord processRecord = getProcessRecordLocked(pid, uid);
    ListenerRecord listenerRecord =
        processRecord == null ? null : processRecord.getListenerRecord(getFeatureName(featureType));

    if (processRecord == null || listenerRecord == null) {
      // Check whether is illegal process from third party application
      // Maybe third application connect service without using
      // VoiceCommandManager
      result = VoiceCommonState.PROCESS_ILLEGAL;
    } else {

      if (setName.equals(listenerRecord.getSetName())) {
        if (listenerRecord == processRecord.getSwipListenerRecord()) {
          // The setName already in used ,so we need to check state
          // Swip is using the set , so we can't delete the set
          result = VoiceCommonState.SET_OCCUPIED;
        } else {
          listenerRecord.setSetName(null);
        }
      }
      // Ask swip to delete the set
      // listenerRecord.selectSet(null);
      if (result == VoiceCommonState.SUCCESS) {
        String swipSet =
            ProcessRecord.getSetNameForSwip(
                processRecord.getProcssName(),
                processRecord.getPid(),
                getFeatureName(featureType),
                setName);
        result = mSwip.deleteSetName(swipSet);
      }
    }
    return result;
  }
  boolean handleAppCrashLocked(
      ProcessRecord app,
      String reason,
      String shortMsg,
      String longMsg,
      String stackTrace,
      AppErrorDialog.Data data) {
    long now = SystemClock.uptimeMillis();

    Long crashTime;
    Long crashTimePersistent;
    if (!app.isolated) {
      crashTime = mProcessCrashTimes.get(app.info.processName, app.uid);
      crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid);
    } else {
      crashTime = crashTimePersistent = null;
    }
    if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) {
      // This process loses!
      Slog.w(TAG, "Process " + app.info.processName + " has crashed too many times: killing!");
      EventLog.writeEvent(
          EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH, app.userId, app.info.processName, app.uid);
      mService.mStackSupervisor.handleAppCrashLocked(app);
      if (!app.persistent) {
        // We don't want to start this process again until the user
        // explicitly does so...  but for persistent process, we really
        // need to keep it running.  If a persistent process is actually
        // repeatedly crashing, then badness for everyone.
        EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid, app.info.processName);
        if (!app.isolated) {
          // XXX We don't have a way to mark isolated processes
          // as bad, since they don't have a peristent identity.
          mBadProcesses.put(
              app.info.processName,
              app.uid,
              new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
          mProcessCrashTimes.remove(app.info.processName, app.uid);
        }
        app.bad = true;
        app.removed = true;
        // Don't let services in this process be restarted and potentially
        // annoy the user repeatedly.  Unless it is persistent, since those
        // processes run critical code.
        mService.removeProcessLocked(app, false, false, "crash");
        mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
        return false;
      }
      mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
    } else {
      TaskRecord affectedTask =
          mService.mStackSupervisor.finishTopRunningActivityLocked(app, reason);
      if (data != null) {
        data.task = affectedTask;
      }
      if (data != null
          && crashTimePersistent != null
          && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) {
        data.repeating = true;
      }
    }

    // Bump up the crash count of any services currently running in the proc.
    for (int i = app.services.size() - 1; i >= 0; i--) {
      // Any services running in the application need to be placed
      // back in the pending list.
      ServiceRecord sr = app.services.valueAt(i);
      sr.crashCount++;
    }

    // If the crashing process is what we consider to be the "home process" and it has been
    // replaced by a third-party app, clear the package preferred activities from packages
    // with a home activity running in the process to prevent a repeatedly crashing app
    // from blocking the user to manually clear the list.
    final ArrayList<ActivityRecord> activities = app.activities;
    if (app == mService.mHomeProcess
        && activities.size() > 0
        && (mService.mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
      for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
        final ActivityRecord r = activities.get(activityNdx);
        if (r.isHomeActivity()) {
          Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
          try {
            ActivityThread.getPackageManager().clearPackagePreferredActivities(r.packageName);
          } catch (RemoteException c) {
            // pm is in same process, this will never happen.
          }
        }
      }
    }

    if (!app.isolated) {
      // XXX Can't keep track of crash times for isolated processes,
      // because they don't have a perisistent identity.
      mProcessCrashTimes.put(app.info.processName, app.uid, now);
      mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now);
    }

    if (app.crashHandler != null) mService.mHandler.post(app.crashHandler);
    return true;
  }
  final void appNotResponding(
      ProcessRecord app,
      ActivityRecord activity,
      ActivityRecord parent,
      boolean aboveSystem,
      final String annotation) {
    ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
    SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);

    if (mService.mController != null) {
      try {
        // 0 == continue, -1 = kill process immediately
        int res = mService.mController.appEarlyNotResponding(app.processName, app.pid, annotation);
        if (res < 0 && app.pid != MY_PID) {
          app.kill("anr", true);
        }
      } catch (RemoteException e) {
        mService.mController = null;
        Watchdog.getInstance().setActivityController(null);
      }
    }

    long anrTime = SystemClock.uptimeMillis();
    if (ActivityManagerService.MONITOR_CPU_USAGE) {
      mService.updateCpuStatsNow();
    }

    synchronized (mService) {
      // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
      if (mService.mShuttingDown) {
        Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
        return;
      } else if (app.notResponding) {
        Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
        return;
      } else if (app.crashing) {
        Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
        return;
      } else if (app.killedByAm) {
        Slog.i(TAG, "App already killed by AM skipping ANR: " + app + " " + annotation);
        return;
      } else if (app.killed) {
        Slog.i(TAG, "Skipping died app ANR: " + app + " " + annotation);
        return;
      }

      // In case we come through here for the same app before completing
      // this one, mark as anring now so we will bail out.
      app.notResponding = true;

      // Log the ANR to the event log.
      EventLog.writeEvent(
          EventLogTags.AM_ANR, app.userId, app.pid, app.processName, app.info.flags, annotation);

      // Dump thread traces as quickly as we can, starting with "interesting" processes.
      firstPids.add(app.pid);

      int parentPid = app.pid;
      if (parent != null && parent.app != null && parent.app.pid > 0) {
        parentPid = parent.app.pid;
      }
      if (parentPid != app.pid) firstPids.add(parentPid);

      if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);

      for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
        ProcessRecord r = mService.mLruProcesses.get(i);
        if (r != null && r.thread != null) {
          int pid = r.pid;
          if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
            if (r.persistent) {
              firstPids.add(pid);
              if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
            } else {
              lastPids.put(pid, Boolean.TRUE);
              if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
            }
          }
        }
      }
    }

    // Log the ANR to the main log.
    StringBuilder info = new StringBuilder();
    info.setLength(0);
    info.append("ANR in ").append(app.processName);
    if (activity != null && activity.shortComponentName != null) {
      info.append(" (").append(activity.shortComponentName).append(")");
    }
    info.append("\n");
    info.append("PID: ").append(app.pid).append("\n");
    if (annotation != null) {
      info.append("Reason: ").append(annotation).append("\n");
    }
    if (parent != null && parent != activity) {
      info.append("Parent: ").append(parent.shortComponentName).append("\n");
    }

    final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);

    File tracesFile =
        mService.dumpStackTraces(
            true, firstPids, processCpuTracker, lastPids, NATIVE_STACKS_OF_INTEREST);

    String cpuInfo = null;
    if (ActivityManagerService.MONITOR_CPU_USAGE) {
      mService.updateCpuStatsNow();
      synchronized (mService.mProcessCpuTracker) {
        cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
      }
      info.append(processCpuTracker.printCurrentLoad());
      info.append(cpuInfo);
    }

    info.append(processCpuTracker.printCurrentState(anrTime));

    Slog.e(TAG, info.toString());
    if (tracesFile == null) {
      // There is no trace file, so dump (only) the alleged culprit's threads to the log
      Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
    }

    mService.addErrorToDropBox(
        "anr", app, app.processName, activity, parent, annotation, cpuInfo, tracesFile, null);

    if (mService.mController != null) {
      try {
        // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
        int res = mService.mController.appNotResponding(app.processName, app.pid, info.toString());
        if (res != 0) {
          if (res < 0 && app.pid != MY_PID) {
            app.kill("anr", true);
          } else {
            synchronized (mService) {
              mService.mServices.scheduleServiceTimeoutLocked(app);
            }
          }
          return;
        }
      } catch (RemoteException e) {
        mService.mController = null;
        Watchdog.getInstance().setActivityController(null);
      }
    }

    // Unless configured otherwise, swallow ANRs in background processes & kill the process.
    boolean showBackground =
        Settings.Secure.getInt(
                mContext.getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0)
            != 0;

    synchronized (mService) {
      mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);

      if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
        app.kill("bg anr", true);
        return;
      }

      // Set the app's notResponding state, and look up the errorReportReceiver
      makeAppNotRespondingLocked(
          app,
          activity != null ? activity.shortComponentName : null,
          annotation != null ? "ANR " + annotation : "ANR",
          info.toString());

      // Bring up the infamous App Not Responding dialog
      Message msg = Message.obtain();
      HashMap<String, Object> map = new HashMap<String, Object>();
      msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
      msg.obj = map;
      msg.arg1 = aboveSystem ? 1 : 0;
      map.put("app", app);
      if (activity != null) {
        map.put("activity", activity);
      }

      mService.mUiHandler.sendMessage(msg);
    }
  }
Esempio n. 25
0
 /** Release occupied swip process record. */
 public void releaseSwipOccupiedProcessLocked() {
   if (mSwipOccupiedProcess != null) {
     mSwipOccupiedProcess.releaseSwipListenerRecord();
     mSwipOccupiedProcess = null;
   }
 }
  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;
    }
  }