+#if CONFIG_EMBEDDED
+static int
+handle_applifecycle(__unused int scope, int action, __unused int policy, int policy_subtype, user_addr_t attrp, proc_t proc, uint64_t target_threadid)
+{
+
+ int error = 0;
+ int state = 0, oldstate = 0;
+ int noteval = 0;
+
+
+
+ switch(policy_subtype) {
+ case PROC_POLICY_APPLIFE_NONE:
+ error = 0;
+ break;
+
+ case PROC_POLICY_APPLIFE_STATE:
+#if CONFIG_MACF
+ error = mac_proc_check_sched(current_proc(), proc);
+ if (error)
+ goto out;
+#endif
+ switch (action) {
+ case PROC_POLICY_ACTION_GET :
+ state = proc_lf_getappstate(proc->task);
+ error = copyout((int *)&state, (user_addr_t)attrp, sizeof(int));
+ break;
+ case PROC_POLICY_ACTION_APPLY :
+ case PROC_POLICY_ACTION_SET :
+ error = copyin((user_addr_t)attrp, (int *)&state, sizeof(int));
+ if ((error == 0) && (state != TASK_APPSTATE_NONE)) {
+ oldstate = proc_lf_getappstate(proc->task);
+ error = proc_lf_setappstate(proc->task, state);
+ if (error == 0) {
+ switch (state) {
+ case TASK_APPSTATE_ACTIVE:
+ noteval = NOTE_APPACTIVE;
+ break;
+ case TASK_APPSTATE_BACKGROUND:
+ noteval = NOTE_APPBACKGROUND;
+ break;
+ case TASK_APPSTATE_NONUI:
+ noteval = NOTE_APPNONUI;
+ break;
+ case TASK_APPSTATE_INACTIVE:
+ noteval = NOTE_APPINACTIVE;
+ break;
+ }
+
+ proc_lock(proc);
+ proc_knote(proc, noteval);
+ proc_unlock(proc);
+ }
+ }
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+
+ case PROC_POLICY_APPLIFE_DEVSTATUS:
+#if CONFIG_MACF
+ /* ToDo - this should be a generic check, since we could potentially hang other behaviours here. */
+ error = mac_proc_check_suspend_resume(current_proc(), MAC_PROC_CHECK_HIBERNATE);
+ if (error) {
+ error = EPERM;
+ goto out;
+ }
+#endif
+ if (action == PROC_POLICY_ACTION_APPLY) {
+ /* Used as a freeze hint */
+ memorystatus_on_inactivity(-1);
+
+ /* in future use devicestatus for pid_socketshutdown() */
+ error = 0;
+ } else {
+ error = EINVAL;
+ }
+ break;
+
+ case PROC_POLICY_APPLIFE_PIDBIND:
+#if CONFIG_MACF
+ error = mac_proc_check_suspend_resume(current_proc(), MAC_PROC_CHECK_PIDBIND);
+ if (error) {
+ error = EPERM;
+ goto out;
+ }
+#endif
+ error = copyin((user_addr_t)attrp, (int *)&state, sizeof(int));
+ if (error != 0)
+ goto out;
+ if (action == PROC_POLICY_ACTION_APPLY) {
+ /* bind the thread in target_thread in current process to target_proc */
+ error = proc_lf_pidbind(current_task(), target_threadid, proc->task, state);
+ } else
+ error = EINVAL;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+out:
+ return(error);
+}
+#endif /* CONFIG_EMBEDDED */
+