Android殺しプロセスに関する方法

8898 ワード

1.1 ActivityManager::forceStopPackage
/**
 * Have the system perform a force stop of everything associated with
 * the given application package.  All processes that share its uid //  UID
 * will be killed, all services it has running stopped, all activities // service activity
 * removed, etc.  In addition, a {@link Intent#ACTION_PACKAGE_RESTARTED} //ACTION_PACKAGE_RESTARTED  
 * broadcast will be sent, so that any of its registered alarms can // alarm notifications
 * be stopped, notifications removed, etc.
 *
 * 

You must hold the permission * {@link android.Manifest.permission#FORCE_STOP_PACKAGES} to be able to * call this method. * * @param packageName The name of the package to be stopped. * @param userId The user for which the running package is to be stopped. * * @hide This is not available to third party applications due to * it allowing them to break other applications by stopping their * services, removing their alarms, etc. */ public void forceStopPackageAsUser(String packageName, int userId) { try { ActivityManagerNative.getDefault().forceStopPackage(packageName, userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }


このメソッドを呼び出します(FORCE_STOP_PACKAGES権限にはシステム署名が必要です).
  • システムは、指定されたパケットに関連するすべてのことを強制的に停止します.
  • は、同じuidを使用するすべてのプロセスを殺し、すべてのサービスを停止し、すべてのactivityを除去する.
  • 登録されたすべてのタイマと通知も削除されます.
  • はまた、起動の自己起動とバックグラウンドの自己起動を禁止する目的を達成することができる.

  • 1.2 PackageManagerServices::setPackageStopppedStateパッケージ停止状態の設定
    /**
     * Set whether the given package should be considered stopped, making
     * it not visible to implicit intents that filter out stopped packages.
     */
    void setPackageStoppedState(String packageName, boolean stopped, int userId);
    

    1.3 Settings::setPackageStoppedStateLPw
    boolean setPackageStoppedStateLPw(PackageManagerService pm, String packageName,
            boolean stopped, boolean allowedByPermission, int uid, int userId) {
        int appId = UserHandle.getAppId(uid);
        final PackageSetting pkgSetting = mPackages.get(packageName);
        ... //     
        if (pkgSetting.getStopped(userId) != stopped) {
            pkgSetting.setStopped(stopped, userId);
            // pkgSetting.pkg.mSetStopped = stopped;
            if (pkgSetting.getNotLaunched(userId)) {
                if (pkgSetting.installerPackageName != null) {
                    pm.notifyFirstLaunch(pkgSetting.name, pkgSetting.installerPackageName, userId);
                }
                pkgSetting.setNotLaunched(false, userId);
            }
            return true;
        }
        return false;
    }
    

    1.4 PackageUserStateはアプリケーションの状態を表す
    // PackageUserState
    public PackageUserState(PackageUserState o) {
        ceDataInode = o.ceDataInode;
        installed = o.installed;
        stopped = o.stopped; // force-stopped
        notLaunched = o.notLaunched;
        hidden = o.hidden;
        suspended = o.suspended;
        blockUninstall = o.blockUninstall;
        enabled = o.enabled;
        lastDisableAppCaller = o.lastDisableAppCaller;
        domainVerificationStatus = o.domainVerificationStatus;
        appLinkGeneration = o.appLinkGeneration;
        disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
        enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
    }
    

    1.5 Stop関連Flag
    /**
     * If set, this intent will not match any components in packages that
     * are currently stopped.  If this is not set, then the default behavior
     * is to include such applications in the result.
     */
    public static final int FLAG_EXCLUDE_STOPPED_PACKAGES = 0x00000010;
    /**
     * If set, this intent will always match any components in packages that
     * are currently stopped.  This is the default behavior when
     * {@link #FLAG_EXCLUDE_STOPPED_PACKAGES} is not set.  If both of these
     * flags are set, this one wins (it allows overriding of exclude for
     * places where the framework may automatically set the exclude flag).
     */
    public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 0x00000020;
    

    ブロードキャストのデフォルト追加FLAG_EXCLUDE_STOPPED_PACKAGES1.6 forcestopのAlarmについてAlarmManagerService処理Intent#ACTION_PACKAGE_RESTARTEDブロードキャスト
    class UninstallReceiver extends BroadcastReceiver {
        public UninstallReceiver() {
            IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
            filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
            filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
            filter.addDataScheme("package");
            getContext().registerReceiver(this, filter);
             // Register for events related to sdcard installation.
            IntentFilter sdFilter = new IntentFilter();
            sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
            sdFilter.addAction(Intent.ACTION_USER_STOPPED);
            sdFilter.addAction(Intent.ACTION_UID_REMOVED);
            getContext().registerReceiver(this, sdFilter);
        }
    
        @Override
        public void onReceive(Context context, Intent intent) {
            ...
            if (pkgList != null && (pkgList.length > 0)) {
                for (String pkg : pkgList) {
                    removeLocked(pkg); //       
                    mPriorities.remove(pkg);
                    for (int i=mBroadcastStats.size()-1; i>=0; i--) {
                        ArrayMap uidStats = mBroadcastStats.valueAt(i);
                        if (uidStats.remove(pkg) != null) {
                            if (uidStats.size() <= 0) {
                                mBroadcastStats.removeAt(i);
                            }
                        }
                    }
                }
            }
        }
    }
    
    
    AlarmManagerServiceの中でこの放送を受信して、この放送のpackage nameを判断して、設置したalarm listの中で、対応するalarmを削除します(AlarmManagerSerivceはいくつかのArrayListを使って異なるtypealarmを保存します).
    2.1 killBackgroundProcesses
    /**
     * Have the system immediately kill all background processes associated
     * with the given package.  This is the same as the kernel killing those //      kill -9
     * processes to reclaim memory; the system will take care of restarting //       
     * these processes in the future as needed.
     *
     * 

    You must hold the permission * {@link android.Manifest.permission#KILL_BACKGROUND_PROCESSES} to be able to * call this method. * * @param packageName The name of the package whose processes are to * be killed. */ public void killBackgroundProcesses(String packageName) { try { ActivityManagerNative.getDefault().killBackgroundProcesses(packageName, UserHandle.myUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }

  • ActivityManagerkillBackgroundProcessesメソッドは、カーネルがそれらのプロセス回収メモリを殺すのと同じ(binderDied処理)指定されたパケットに関連付けられたすべてのバックグラウンドプロセスを直ちに殺すことができるが、これらのプロセスは将来のある時点で使用する必要がある場合、再起動される.
  • この方法には、android.permission.KILL_BACKGROUND_PROCESSESの権限が必要である.

  • 2.2 Process::killProcessQuiet
    /**
     * @hide
     * Private impl for avoiding a log message...  DO NOT USE without doing
     * your own log, or the Android Illuminati will find you some night and
     * beat you up.
     */
    public static final void killProcessQuiet(int pid) {
        sendSignalQuiet(pid, SIGNAL_KILL);
    }
    

    2.3 Process::killProcess
    /**
     * Kill the process with the given PID.
     * Note that, though this API allows us to request to
     * kill any process based on its PID, the kernel will
     * still impose standard restrictions on which PIDs you //           kill pid
     * are actually able to kill.  Typically(  ) this means only
     * the process running the caller's packages/application      
     * and any additional processes created by that app; packages
     * sharing a common UID will also be able to kill each //    Uid 
     * other's processes.
     */
    public static final void killProcess(int pid) {
        sendSignal(pid, SIGNAL_KILL);
    }
    

    2.4 Process::sendSignal
    void android_os_Process_sendSignal(JNIEnv* env, jobject clazz, jint pid, jint sig)
    {
        if (pid > 0) {
            ALOGI("Sending signal. PID: %" PRId32 " SIG: %" PRId32, pid, sig); //   
            kill(pid, sig);
        }
    }
    
    void android_os_Process_sendSignalQuiet(JNIEnv* env, jobject clazz, jint pid, jint sig)
    {
        if (pid > 0) {
            kill(pid, sig);
        }
    }
    
    sendSignalsendSignalQuietの唯一の違いは、ALOGI()という行のコードがあるかどうかです.Process.killはカーネルkill -9によってプロセスを殺し、そのプロセスのIBinder.DeathRecipientによってプロセス情報のクリーンアップを行う
    リファレンス
    AndroidでのAppの停止状態について