Exemple #1
0
/** Disable automatic suspend and remove wakelocks mce might hold
 *
 * This function should be called just before mce process terminates
 * so that we do not leave the system in a non-functioning state
 */
static void mce_cleanup_wakelocks(void)
{
	/* We are on exit path -> block suspend for good */
	wakelock_block_suspend_until_exit();

	wakelock_unlock("mce_display_on");
	wakelock_unlock("mce_input_handler");
}
Exemple #2
0
Fichier : mce.c Projet : oleid/mce
/** Disable automatic suspend and remove wakelocks mce might hold
 *
 * This function should be called just before mce process terminates
 * so that we do not leave the system in a non-functioning state
 */
static void mce_cleanup_wakelocks(void)
{
	/* We are on exit path -> block suspend for good */
	wakelock_block_suspend_until_exit();

	wakelock_unlock("mce_display_on");
	wakelock_unlock("mce_input_handler");
	wakelock_unlock("mce_cpu_keepalive");
	wakelock_unlock("mce_display_stm");
	wakelock_unlock("mce_powerkey_stm");
	wakelock_unlock("mce_proximity_stm");
	wakelock_unlock("mce_bluez_wait");
	wakelock_unlock("mce_led_breathing");
	wakelock_unlock("mce_lpm_off");
	wakelock_unlock("mce_tklock_notify");
}
Exemple #3
0
static int android_wakelock_release(struct wakelock *lock)
{
	if (lock == NULL)
		return -EINVAL;

	DBG("lock %p name %s acquisitions %d",
		lock, lock->name, lock->acquisitions);

	if (!lock->acquisitions) {
		ofono_warn("Attempted to release already released lock %s", lock->name);
		return -EINVAL;
	}

	if (lock->acquisitions > 1) {
		lock->acquisitions--;
		DBG("lock %s released acquisitions %d", lock->name, lock->acquisitions);
		return 0;
	}

	if (wakelock_unlock(lock->name) < 0)
		return -EIO;

	lock->acquisitions = 0;

	DBG("lock %s was released", lock->name);

	return 0;
}
Exemple #4
0
/** Set keepalive state
 *
 * @param active  true to start keepalive, false to end keepalive
 */
static void cka_state_set(bool active)
{
  static bool keepalive_is_active = false;
  static bool flagged = false;
  static tick_t started = 0;

  if( keepalive_is_active != active )
  {
    tick_t now = cka_tick_get_current();

    if( (keepalive_is_active = active) )
    {
#ifdef ENABLE_WAKELOCKS
      wakelock_lock(cpu_wakelock, -1);
#endif
      started = now;
      mce_log(LL_DEVEL, "keepalive started");
    }
    else
    {
      tick_t dur = now - started;

      if( dur > KEEPALIVE_STATE_WARN_LIMIT_MS )
      {
        mce_log(LL_CRIT, "long keepalive stopped after %"PRId64" ms", dur);
      }
      else
      {
        mce_log(LL_DEVEL, "keepalive stopped after %"PRId64" ms", dur);
      }

      flagged = false;

#ifdef ENABLE_WAKELOCKS
      wakelock_unlock(cpu_wakelock);
#endif
    }
  }
  else if( keepalive_is_active && !flagged ) {
    tick_t now = cka_tick_get_current();
    tick_t dur = now - started;
    if( dur > KEEPALIVE_STATE_WARN_LIMIT_MS )
    {
      flagged = true;
      mce_log(LL_CRIT, "long keepalive active after %"PRId64" ms", dur);
    }
  }
}
Exemple #5
0
/** Handle triggering of cpu-keepalive timer
 *
 * Releases cpu keepalive wakelock and thus allows the system to
 * enter late suspend according to other policies.
 *
 * @param data (not used)
 *
 * @return FALSE (to stop then timer from repeating)
 */
static
gboolean
cpu_keepalive_timer_cb(gpointer data)
{
  (void)data;

  if( timer_id != 0 )
  {
    mce_log(LL_NOTICE, "cpu-keepalive ended");
    timer_id = 0;

#ifdef ENABLE_WAKELOCKS
    wakelock_unlock(cpu_wakelock);
#endif
  }

  return FALSE;
}
Exemple #6
0
/** Transfer resume-due-to-rtc-input wakelock from dsme to mce
 *
 * @param dbus_name name of the client issuing the request
 */
static
void
cpu_keepalive_wakeup(const gchar *dbus_name)
{
  // FIXME: we should check that the dbus_name == DSME
  (void)dbus_name;

  /* Time of wakeup received */
  wakeup_started = cpu_keepalive_get_time();

  /* Timeout for the 1st keepalive message to come through */
  wakeup_timeout = wakeup_started + MCE_RTC_WAKEUP_1ST_TIMEOUT_SECONDS;

  cpu_keepalive_rethink();

  mce_log(LL_NOTICE, "rtc wakeup finished");
#ifdef ENABLE_WAKELOCKS
  wakelock_unlock(rtc_wakelock);
#endif
}
Exemple #7
0
/** Evaluate need for suspend blocking
 */
static void mia_keepalive_rethink(void)
{
    static bool have_lock = false;

    bool need_lock = (mia_keepalive_id != 0);

    if( have_lock == need_lock )
        goto EXIT;

    mce_log(LL_DEBUG, "inactivity notify wakelock: %s",
            need_lock ? "OBTAIN" : "RELEASE");

    if( (have_lock = need_lock) )
        wakelock_lock("mce_inactivity_notify", -1);
    else
        wakelock_unlock("mce_inactivity_notify");

EXIT:
    return;
}
Exemple #8
0
/** Transfer resume-due-to-rtc-input wakelock from dsme to mce
 *
 * @param dbus_name  name of the client issuing the request
 */
static
void
cka_clients_handle_wakeup(const gchar *dbus_name)
{
  // FIXME: we should check that the dbus_name == DSME
  (void)dbus_name;

  /* Time of wakeup received */
  cka_clients_wakeup_started = cka_tick_get_current();

  /* Timeout for the 1st keepalive message to come through */
  cka_clients_wakeup_timeout =
    cka_tick_get_timeout(cka_clients_wakeup_started,
                         MCE_RTC_WAKEUP_1ST_TIMEOUT_S);

  cka_state_rethink();

  mce_log(LL_NOTICE, "rtc wakeup finished");
#ifdef ENABLE_WAKELOCKS
  wakelock_unlock(rtc_wakelock);
#endif
}
Exemple #9
0
/**
 * Callback for successful chunk I/O
 *
 * @param source The source of the activity
 * @param condition The I/O condition
 * @param data The iomon structure
 * @return Depending on error policy this function either exits
 *         or returns TRUE
 */
static gboolean io_chunk_cb(GIOChannel *source,
			    GIOCondition condition,
			    gpointer data)
{
	iomon_struct *iomon = data;
	gchar *buffer = NULL;
	gsize bytes_want = 4096;
	gsize bytes_read = 0;
	gsize chunks_read = 0;
	gsize chunks_done = 0;
	GIOStatus io_status;
	GError *error = NULL;
	gboolean status = TRUE;

	/* Silence warnings */
	(void)condition;

	if (iomon == NULL) {
		mce_log(LL_CRIT, "iomon == NULL!");
		status = FALSE;
		goto EXIT;
	}

	iomon->latest_io_condition = 0;

	/* Seek to the beginning of the file before reading if needed */
	if (iomon->rewind == TRUE) {
		g_io_channel_seek_position(source, 0, G_SEEK_SET, &error);
		if( error ) {
			mce_log(LL_ERR,	"%s: seek error: %s",
				iomon->file, error->message);
		}

		/* Reset errno,
		 * to avoid false positives down the line
		 */
		errno = 0;
		g_clear_error(&error);
	}

	if( iomon->chunk_size < bytes_want ) {
		bytes_want -= bytes_want % iomon->chunk_size;
	} else {
		bytes_want = iomon->chunk_size;
	}

	buffer = g_malloc(bytes_want);

#ifdef ENABLE_WAKELOCKS
	/* Since the locks on kernel side are released once all
	 * events are read, we must obtain the userspace lock
	 * before reading the available data */
	wakelock_lock("mce_input_handler", -1);
#endif

	io_status = g_io_channel_read_chars(source, buffer,
					    bytes_want, &bytes_read, &error);


	/* If the read was interrupted, ignore */
	if (io_status == G_IO_STATUS_AGAIN) {
		g_clear_error(&error);
	}

	if( bytes_read % iomon->chunk_size ) {
		mce_log(LL_WARN, "Incomplete chunks read from: %s", iomon->file);
	}

	/* Process the data, and optionally ignore some of it */
	if( (chunks_read = bytes_read / iomon->chunk_size) ) {
		gchar *chunk = buffer;
		for( ; chunks_done < chunks_read ; chunk += iomon->chunk_size ) {
			++chunks_done;
			if (iomon->callback(chunk, iomon->chunk_size) != TRUE) {
				continue;
			}
			/* if possible, seek to the end of file */
			if (iomon->seekable) {
				g_io_channel_seek_position(iomon->iochan, 0,
							   G_SEEK_END, &error);
			}
			/* in any case ignore rest of the data already read */
			break;
		}
	}

	mce_log(LL_INFO, "%s: status=%s, data=%d/%d=%d+%d, skipped=%d",
		iomon->file, io_status_name(io_status),
		bytes_read, (int)iomon->chunk_size, chunks_read,
		bytes_read % (int)iomon->chunk_size, chunks_read - chunks_done);

#ifdef ENABLE_WAKELOCKS
	/* Release the lock after we're done with processing it */
	wakelock_unlock("mce_input_handler");
#endif


	g_free(buffer);

	/* Were there any errors? */
	if (error != NULL) {
		mce_log(LL_ERR,
			"Error when reading from %s: %s",
			iomon->file, error->message);

		if ((error->code == G_IO_CHANNEL_ERROR_FAILED) &&
		    (errno == ENODEV) &&
		    (iomon->seekable)) {
			errno = 0;
			g_clear_error(&error);
			g_io_channel_seek_position(iomon->iochan, 0,
						   G_SEEK_END, &error);
			if( error ) {
				mce_log(LL_ERR,	"%s: seek error: %s",
					iomon->file, error->message);
			}
		} else {
			status = FALSE;
		}

		/* Reset errno,
		 * to avoid false positives down the line
		 */
		errno = 0;
		g_clear_error(&error);
	} else if ((bytes_read == 0) &&
		   (io_status != G_IO_STATUS_EOF) &&
		   (io_status != G_IO_STATUS_AGAIN)) {
		mce_log(LL_ERR,
			"Empty read from %s",
			iomon->file);
	}

EXIT:
	if ((status == FALSE) &&
	    (iomon != NULL) &&
	    (iomon->error_policy == MCE_IO_ERROR_POLICY_EXIT)) {
		// FIXME: this is not how one should exit from mainloop
		mce_quit_mainloop();
		exit(EXIT_FAILURE);
	}

	return TRUE;
}