def _new_activity(self, activity_id, tp, room):
        try:
            objid = self._get_next_object_id()
            activity = Activity(self._session_bus, objid, self, tp, room,
                                id=activity_id)
        except Exception:
            # FIXME: catching bare Exception considered harmful
            _logger.debug("Invalid activity:", exc_info=1)
            try:
                del self._activities_by_handle[tp][room]
            except KeyError:
                pass
            return None

        activity.connect("validity-changed",
                         self._activity_validity_changed_cb)
        activity.connect("disappeared", self._activity_disappeared_cb)
        self._activities_by_id[activity_id] = activity
        self._activities_by_handle[tp][room] = activity
        return activity
        except ValueError, e:
            async_err_cb(e)
            return

        objid = self._get_next_object_id()
        # XXX: is the preferred Telepathy plugin always the right way to
        # share the activity?
        # We set private=True here - when the activity becomes shared
        # via join(), we'll set private to the correct value.
        activity = Activity(self._session_bus, objid, self,
                            self._get_preferred_plugin(), 0,
                            id=actid, type=atype,
                            name=name, color=self._owner.props.color,
                            local=True, private=True, tags=tags)

        activity.connect("validity-changed",
                         self._activity_validity_changed_cb)
        activity.connect("disappeared", self._activity_disappeared_cb)
        self._activities_by_id[actid] = activity

        def activity_shared():
            tp, room = activity.room_details
            self._activities_by_handle[tp][room] = activity
            async_cb(activity.object_path())

        activity.join(activity_shared, async_err_cb, sharing=True,
                      private=private, sender=sender)

        # local activities are valid at creation by definition, but we can't
        # connect to the activity's validity-changed signal until its already
        # issued the signal, which happens in the activity's constructor
        # for local activities.